GitHubLionel / wxMathPlot

An enhanced version of the wxMathPlot component for wxWidgets
14 stars 5 forks source link

show image in the control, I add another function in the demo application #69

Open asmwarrior opened 4 days ago

asmwarrior commented 4 days ago
From bf3f8495dda1862c84141297fb86d7eae64eedc4 Mon Sep 17 00:00:00 2001
From: asmwarrior <hidden@hidden.com>
Date: Tue, 26 Nov 2024 11:05:25 +0800
Subject: [PATCH] draw an image with transparency

---
 MathPlotDemo/MathPlotDemoMain.cpp          | 108 +++++++++++++++------
 MathPlotDemo/MathPlotDemoMain.h            |  23 ++---
 MathPlotDemo/wxsmith/MathPlotDemoframe.wxs |   8 ++
 3 files changed, 93 insertions(+), 46 deletions(-)

diff --git a/MathPlotDemo/MathPlotDemoMain.cpp b/MathPlotDemo/MathPlotDemoMain.cpp
index ff4ff5e..6c9fa38 100644
--- a/MathPlotDemo/MathPlotDemoMain.cpp
+++ b/MathPlotDemo/MathPlotDemoMain.cpp
@@ -45,20 +45,13 @@ wxString wxBuildInfo(wxBuildInfoFormat format)
 }

 //(*IdInit(MathPlotDemoFrame)
-const long MathPlotDemoFrame::ID_BUTTON1 = wxNewId();
-const long MathPlotDemoFrame::ID_BUTTON2 = wxNewId();
-const long MathPlotDemoFrame::ID_BUTTON3 = wxNewId();
-const long MathPlotDemoFrame::ID_BUTTON4 = wxNewId();
-const long MathPlotDemoFrame::ID_BUTTON5 = wxNewId();
-const long MathPlotDemoFrame::ID_BUTTON6 = wxNewId();
-const long MathPlotDemoFrame::ID_CHECKBOX1 = wxNewId();
-const long MathPlotDemoFrame::ID_PANEL1 = wxNewId();
-const long MathPlotDemoFrame::ID_MATHPLOT1 = wxNewId();
-const long MathPlotDemoFrame::ID_PANEL2 = wxNewId();
-const long MathPlotDemoFrame::idMenuPreview = wxNewId();
-const long MathPlotDemoFrame::idMenuPrint = wxNewId();
-const long MathPlotDemoFrame::idMenuExit = wxNewId();
-const long MathPlotDemoFrame::idMenuAbout = wxNewId();
+const wxWindowID MathPlotDemoFrame::ID_PANEL1 = wxNewId();
+const wxWindowID MathPlotDemoFrame::ID_MATHPLOT1 = wxNewId();
+const wxWindowID MathPlotDemoFrame::ID_PANEL2 = wxNewId();
+const wxWindowID MathPlotDemoFrame::idMenuPreview = wxNewId();
+const wxWindowID MathPlotDemoFrame::idMenuPrint = wxNewId();
+const wxWindowID MathPlotDemoFrame::idMenuExit = wxNewId();
+const wxWindowID MathPlotDemoFrame::idMenuAbout = wxNewId();
 //*)

 BEGIN_EVENT_TABLE(MathPlotDemoFrame,wxFrame)
@@ -84,25 +77,25 @@ MathPlotDemoFrame::MathPlotDemoFrame(wxWindow* parent,wxWindowID id)
     pLog = new wxPanel(this, ID_PANEL1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _T("ID_PANEL1"));
     pLog->SetMinSize(wxSize(120,-1));
     BoxSizer2 = new wxBoxSizer(wxVERTICAL);
-    bDraw = new wxButton(pLog, ID_BUTTON1, _("Draw sinus"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON1"));
+    bDraw = new wxButton(pLog, wxID_ANY, _("Draw sinus"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
     BoxSizer2->Add(bDraw, 0, wxALL|wxEXPAND, 10);
-    bSample = new wxButton(pLog, ID_BUTTON2, _("Draw Sample"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON2"));
+    bSample = new wxButton(pLog, wxID_ANY, _("Draw Sample"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
     BoxSizer2->Add(bSample, 0, wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND, 10);
-    bBar = new wxButton(pLog, ID_BUTTON3, _("Draw Bar"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON3"));
+    bBar = new wxButton(pLog, wxID_ANY, _("Draw Bar"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
     BoxSizer2->Add(bBar, 0, wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND, 10);
-    bLog = new wxButton(pLog, ID_BUTTON4, _("Log Y sample"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON4"));
+    bLog = new wxButton(pLog, wxID_ANY, _("Log Y sample"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
     BoxSizer2->Add(bLog, 0, wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND, 10);
-    bLogXY = new wxButton(pLog, ID_BUTTON5, _("Log XY sample"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON5"));
+    bLogXY = new wxButton(pLog, wxID_ANY, _("Log XY sample"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
     BoxSizer2->Add(bLogXY, 0, wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND, 10);
-    bBarChart = new wxButton(pLog, ID_BUTTON6, _("Draw BarChart"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON6"));
+    bBarChart = new wxButton(pLog, wxID_ANY, _("Draw BarChart"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
     BoxSizer2->Add(bBarChart, 0, wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND, 10);
-    cbFreeLine = new wxCheckBox(pLog, ID_CHECKBOX1, _("Free line"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_CHECKBOX1"));
+    bImage = new wxButton(pLog, wxID_ANY, _("Draw Image"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
+    BoxSizer2->Add(bImage, 0, wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND, 10);
+    cbFreeLine = new wxCheckBox(pLog, wxID_ANY, _("Free line"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
     cbFreeLine->SetValue(false);
     cbFreeLine->SetToolTip(_("Free drawing on the plot area. Left click and move the mouse. Illustration of OnUserMouseAction"));
     BoxSizer2->Add(cbFreeLine, 0, wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND, 10);
     pLog->SetSizer(BoxSizer2);
-    BoxSizer2->Fit(pLog);
-    BoxSizer2->SetSizeHints(pLog);
     AuiManager1->AddPane(pLog, wxAuiPaneInfo().Name(_T("PaneName0")).DefaultPane().Caption(_("Log")).CaptionVisible().CloseButton(false).Left().Floatable(false).MinSize(wxSize(120,-1)).Movable(false));
     pPlot = new wxPanel(this, ID_PANEL2, wxPoint(227,228), wxDefaultSize, wxTAB_TRAVERSAL, _T("ID_PANEL2"));
     BoxSizer1 = new wxBoxSizer(wxVERTICAL);
@@ -111,8 +104,6 @@ MathPlotDemoFrame::MathPlotDemoFrame(wxWindow* parent,wxWindowID id)
     mPlot->Fit();
     BoxSizer1->Add(mPlot, 1, wxALL|wxEXPAND, 5);
     pPlot->SetSizer(BoxSizer1);
-    BoxSizer1->Fit(pPlot);
-    BoxSizer1->SetSizeHints(pPlot);
     AuiManager1->AddPane(pPlot, wxAuiPaneInfo().Name(_T("PaneName1")).DefaultPane().Caption(_("Plot")).CaptionVisible().MaximizeButton().CloseButton(false).Center());
     AuiManager1->Update();
     MenuBar1 = new wxMenuBar();
@@ -134,13 +125,14 @@ MathPlotDemoFrame::MathPlotDemoFrame(wxWindow* parent,wxWindowID id)
     MenuBar1->Append(Menu3, _("Help"));
     SetMenuBar(MenuBar1);

-    Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MathPlotDemoFrame::OnbDrawClick, this, ID_BUTTON1);
-    Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MathPlotDemoFrame::OnbSampleClick, this, ID_BUTTON2);
-    Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MathPlotDemoFrame::OnbBarClick, this, ID_BUTTON3);
-    Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MathPlotDemoFrame::OnbLogClick, this, ID_BUTTON4);
-    Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MathPlotDemoFrame::OnbLogXYClick, this, ID_BUTTON5);
-    Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MathPlotDemoFrame::OnbBarChartClick, this, ID_BUTTON6);
-    Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, &MathPlotDemoFrame::OncbFreeLineClick, this, ID_CHECKBOX1);
+    bDraw->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MathPlotDemoFrame::OnbDrawClick, this);
+    bSample->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MathPlotDemoFrame::OnbSampleClick, this);
+    bBar->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MathPlotDemoFrame::OnbBarClick, this);
+    bLog->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MathPlotDemoFrame::OnbLogClick, this);
+    bLogXY->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MathPlotDemoFrame::OnbLogXYClick, this);
+    bBarChart->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MathPlotDemoFrame::OnbBarChartClick, this);
+    bImage->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MathPlotDemoFrame::OnbImageClick, this);
+    cbFreeLine->Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, &MathPlotDemoFrame::OncbFreeLineClick, this);
     Bind(wxEVT_COMMAND_MENU_SELECTED, &MathPlotDemoFrame::OnmiPreviewSelected, this, idMenuPreview);
     Bind(wxEVT_COMMAND_MENU_SELECTED, &MathPlotDemoFrame::OnmiPrintSelected, this, idMenuPrint);
     Bind(wxEVT_COMMAND_MENU_SELECTED, &MathPlotDemoFrame::OnmiQuitSelected, this, idMenuExit);
@@ -449,3 +441,55 @@ void MathPlotDemoFrame::OnmiPrintSelected(wxCommandEvent &WXUNUSED(event))
   mpPrintout printout(mPlot, wxT("Plot print"));
   printer.Print(this, &printout, true);
 }
+
+// Function to interpolate between two colors
+wxColour InterpolateColor(const wxColour& start, const wxColour& end, double factor)
+{
+    return wxColour(
+        start.Red()   + factor * (end.Red() - start.Red()),
+        start.Green() + factor * (end.Green() - start.Green()),
+        start.Blue()  + factor * (end.Blue() - start.Blue()),
+        start.Alpha() + factor * (end.Alpha() - start.Alpha())
+    );
+}
+
+// Create a wxImage with a rainbow gradient
+wxImage CreateRainbowImage(int width, int height, bool withAlpha = false)
+{
+    wxImage image(width, height);
+
+    if (withAlpha) {
+        image.InitAlpha(); // Initialize the alpha channel
+    }
+
+    // Define colors for gradient
+    wxColour startColor(255, 0, 0);   // Red
+    wxColour endColor(0, 0, 255);     // Blue
+
+    for (int x = 0; x < width; ++x) {
+        double factor = static_cast<double>(x) / (width - 1);
+        wxColour currentColor = InterpolateColor(startColor, endColor, factor);
+
+        for (int y = 0; y < height; ++y) {
+            image.SetRGB(x, y, currentColor.Red(), currentColor.Green(), currentColor.Blue());
+            if (withAlpha) {
+                image.SetAlpha(x, y, 255 - static_cast<unsigned char>(factor * 255)); // Optional transparency
+            }
+        }
+    }
+
+    return image;
+}
+
+void MathPlotDemoFrame::OnbImageClick(wxCommandEvent& event)
+{
+  CleanPlot();
+
+  // Create rainbow image
+  wxImage rainbowImage = CreateRainbowImage(512, 512, true);
+  mpBitmapLayer* bitmapLayer = new mpBitmapLayer();
+  bitmapLayer->SetBitmap(rainbowImage, 0, 0, 512, 512);
+
+  mPlot->AddLayer(bitmapLayer);
+  mPlot->Fit();
+}
diff --git a/MathPlotDemo/MathPlotDemoMain.h b/MathPlotDemo/MathPlotDemoMain.h
index 549d36b..5023c0d 100644
--- a/MathPlotDemo/MathPlotDemoMain.h
+++ b/MathPlotDemo/MathPlotDemoMain.h
@@ -42,23 +42,17 @@ class MathPlotDemoFrame: public wxFrame
         void OnmiPrintSelected(wxCommandEvent& event);
         void OnbBarChartClick(wxCommandEvent& event);
         void OncbFreeLineClick(wxCommandEvent& event);
+        void OnbImageClick(wxCommandEvent& event);
         //*)

         //(*Identifiers(MathPlotDemoFrame)
-        static const long ID_BUTTON1;
-        static const long ID_BUTTON2;
-        static const long ID_BUTTON3;
-        static const long ID_BUTTON4;
-        static const long ID_BUTTON5;
-        static const long ID_BUTTON6;
-        static const long ID_CHECKBOX1;
-        static const long ID_PANEL1;
-        static const long ID_MATHPLOT1;
-        static const long ID_PANEL2;
-        static const long idMenuPreview;
-        static const long idMenuPrint;
-        static const long idMenuExit;
-        static const long idMenuAbout;
+        static const wxWindowID ID_PANEL1;
+        static const wxWindowID ID_MATHPLOT1;
+        static const wxWindowID ID_PANEL2;
+        static const wxWindowID idMenuPreview;
+        static const wxWindowID idMenuPrint;
+        static const wxWindowID idMenuExit;
+        static const wxWindowID idMenuAbout;
         //*)

         //(*Declarations(MathPlotDemoFrame)
@@ -67,6 +61,7 @@ class MathPlotDemoFrame: public wxFrame
         wxButton* bBar;
         wxButton* bBarChart;
         wxButton* bDraw;
+        wxButton* bImage;
         wxButton* bLog;
         wxButton* bLogXY;
         wxButton* bSample;
diff --git a/MathPlotDemo/wxsmith/MathPlotDemoframe.wxs b/MathPlotDemo/wxsmith/MathPlotDemoframe.wxs
index 232eb25..507de4a 100644
--- a/MathPlotDemo/wxsmith/MathPlotDemoframe.wxs
+++ b/MathPlotDemo/wxsmith/MathPlotDemoframe.wxs
@@ -59,6 +59,14 @@
                            <flag>wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND</flag>
                            <border>10</border>
                        </object>
+                       <object class="sizeritem">
+                           <object class="wxButton" name="" variable="bImage" member="yes">
+                               <label>Draw Image</label>
+                               <handler function="OnbImageClick" entry="EVT_BUTTON" />
+                           </object>
+                           <flag>wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND</flag>
+                           <border>10</border>
+                       </object>
                        <object class="sizeritem">
                            <object class="wxCheckBox" name="" variable="cbFreeLine" member="yes">
                                <label>Free line</label>
-- 
2.41.0.windows.1

The above is the code, I'm using the latest C::B, so the wxSmith may have different generated code than yours.

But the logic is simple, I just add a new button and an event handler for that button to show the image.

image

The problem is that after I draw the image, I try to click on another button, such as "draw sinus", but the image is not deleted by the function CleanPlot(), I'm not sure why.

asmwarrior commented 4 days ago
void MathPlotDemoFrame::CleanPlot(void)
{
  mPlot->DelAllPlot(true);
  bottomAxis->SetAlign(mpALIGN_CENTERX);
  bottomAxis->SetLogAxis(false);
  leftAxis->SetAlign(mpALIGN_CENTERY);
  leftAxis->SetLogAxis(false);
  bottomAxis->SetAuto(true);
  mPlot->DelLayer(mPlot->GetLayerByName(_T("BarChart")), true);
  mPlot->DelLayer(mPlot->GetLayerByClassName("mpBitmapLayer"), true);
}

OK, adding the last line in the above function solved the remaining bitmap issue.

DRNadler commented 4 days ago

Will you add a pull request?

asmwarrior commented 1 day ago

I'm not sure which part of my patch should be put in the pull request. Some of the code changes are from the wxSmith generation, I think I'm using the latest wxSmith code, while Lionel's wxSmith maybe a littler old, So, they have different code generation styles.

That's why I put the full patch here.

GitHubLionel commented 1 day ago

I add your code to the demo program. About wxSmith, why the official release of C::B is always the 20.03 ? I use this release to be compatible (I just replace connect by bind for events).

asmwarrior commented 21 hours ago

I add your code to the demo program. About wxSmith, why the official release of C::B is always the 20.03 ? I use this release to be compatible (I just replace connect by bind for events).

Hi, thanks.

I'm using the C::B nightly build version, for example: Nightly builds

Or, I have a github bot to build it, see here: asmwarrior/x86-codeblocks-builds: Automatically built codeblocks for both 32b and 64b Windows systems.

I think a new release will be 24.12. There is no official release between 20.03 to 24.12.

In one option of wxSmith(you can see it in its setting dialog), we can choose whether to generate the "Bind" or "Connect" option. I think the "Connect" is the default option.

GitHubLionel commented 12 hours ago

Ok, I have updated with your latest build of C::B