changeset 2917:77e5d6743013

C++: Implement most of Page 2 (Render) except the actual rendering.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Wed, 28 Dec 2022 09:32:27 +0000
parents fe43f8667d3d
children 7d3276f80132
files dw.hpp dwtestoo.cpp
diffstat 2 files changed, 356 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/dw.hpp	Wed Dec 28 03:28:31 2022 +0000
+++ b/dw.hpp	Wed Dec 28 09:32:27 2022 +0000
@@ -778,10 +778,22 @@
         SetHandle(reinterpret_cast<void *>(newpixmap));
     }
     HPIXMAP hpixmap; 
+    unsigned long pwidth, pheight;
 public:
     // Constructors
-    Pixmap(HWND window, unsigned long width, unsigned long height, int depth) { SetHPIXMAP(dw_pixmap_new(window, width, height, depth)); }
-    Pixmap(HWND window, unsigned long width, unsigned long height) { SetHPIXMAP(dw_pixmap_new(window, width, height, 32)); }
+    Pixmap(Render *window, unsigned long width, unsigned long height, int depth) { 
+        SetHPIXMAP(dw_pixmap_new(window ? window->GetHWND() : DW_NOHWND, width, height, depth)); 
+        pwidth = width; pheight = height; 
+    }
+    Pixmap(Render *window, unsigned long width, unsigned long height) {
+        SetHPIXMAP(dw_pixmap_new(window ? window->GetHWND() : DW_NOHWND, width, height, 32)); 
+        pwidth = width; pheight = height;
+    }
+    Pixmap(Render *window, const char *filename) { 
+        SetHPIXMAP(dw_pixmap_new_from_file(window ? window->GetHWND() : DW_NOHWND, filename));
+        pwidth = hpixmap ? DW_PIXMAP_WIDTH(hpixmap) : 0;
+        pheight = hpixmap ? DW_PIXMAP_HEIGHT(hpixmap) : 0;
+    }
 
     // User functions
     HPIXMAP GetHPIXMAP() { return hpixmap; }
@@ -805,6 +817,9 @@
     }
     int SetFont(const char *fontname) { return dw_pixmap_set_font(hpixmap, fontname); }
     void GetTextExtents(const char *text, int *width, int *height) { dw_font_text_extents_get(DW_NOHWND, hpixmap, text, width, height); }
+    void SetTransparentColor(unsigned long color) { dw_pixmap_set_transparent_color(hpixmap, color); }
+    unsigned long GetWidth() { return pwidth; }
+    unsigned long GetHeight() { return pheight; }
 };
 
 // Need to declare these here after Pixmap is defined
@@ -990,24 +1005,24 @@
     }
 };
 
-class Combobox : public TextEntry, public ListBoxes
+class ComboBox : public TextEntry, public ListBoxes
 {
 public:
     // Constructors
-    Combobox(const char *text, unsigned long id) { SetHWND(dw_combobox_new(text, id)); }
-    Combobox(unsigned long id) { SetHWND(dw_combobox_new("", id)); }
-    Combobox(const char *text) { SetHWND(dw_combobox_new(text, 0)); }
-    Combobox() { SetHWND(dw_combobox_new("", 0)); }
+    ComboBox(const char *text, unsigned long id) { SetHWND(dw_combobox_new(text, id)); }
+    ComboBox(unsigned long id) { SetHWND(dw_combobox_new("", id)); }
+    ComboBox(const char *text) { SetHWND(dw_combobox_new(text, 0)); }
+    ComboBox() { SetHWND(dw_combobox_new("", 0)); }
 };
 
-class Listbox : public ListBoxes
+class ListBox : public ListBoxes
 {
 public:
     // Constructors
-    Listbox(unsigned long id, int multi) { SetHWND(dw_listbox_new(id, multi)); }
-    Listbox(unsigned long id) { SetHWND(dw_listbox_new(id, FALSE)); }
-    Listbox(int multi) { SetHWND(dw_listbox_new(0, multi)); }
-    Listbox() { SetHWND(dw_listbox_new(0, FALSE)); }
+    ListBox(unsigned long id, int multi) { SetHWND(dw_listbox_new(id, multi)); }
+    ListBox(unsigned long id) { SetHWND(dw_listbox_new(id, FALSE)); }
+    ListBox(int multi) { SetHWND(dw_listbox_new(0, multi)); }
+    ListBox() { SetHWND(dw_listbox_new(0, FALSE)); }
 };
 
 // Base class for several ranged type widgets
@@ -1069,12 +1084,12 @@
     void SetPos(unsigned int position) { dw_slider_set_pos(hwnd, position); }
 };
 
-class Scrollbar : public Ranged
+class ScrollBar : public Ranged
 {
 public:
     // Constructors
-    Scrollbar(int orient, unsigned long id) { SetHWND(dw_scrollbar_new(orient, id)); Setup(); }
-    Scrollbar(int orient) { SetHWND(dw_scrollbar_new(orient, 0)); Setup(); }
+    ScrollBar(int orient, unsigned long id) { SetHWND(dw_scrollbar_new(orient, id)); Setup(); }
+    ScrollBar(int orient) { SetHWND(dw_scrollbar_new(orient, 0)); Setup(); }
 
     // User functions
     unsigned int GetPos() { return dw_scrollbar_get_pos(hwnd); }
@@ -1642,6 +1657,7 @@
     void GetEnvironment(DWEnv *env) { dw_environment_query(env); }
     int GetScreenWidth() { return dw_screen_width(); }
     int GetScreenHeight() { return dw_screen_height(); }
+    void GetPointerPos(long *x, long *y) { dw_pointer_query_pos(x, y); }
     unsigned long GetColorDepth() { return dw_color_depth_get(); }
     char *GetClipboard() { return dw_clipboard_get_text(); }
     void SetClipboard(const char *text) { if(text) dw_clipboard_set_text(text, (int)strlen(text)); }
@@ -1657,6 +1673,8 @@
     HICN LoadIcon(const char *filename) { return dw_icon_load_from_file(filename); }
     HICN LoadIcon(const char *data, int len) { return dw_icon_load_from_data(data, len); }
     void FreeIcon(HICN icon) { dw_icon_free(icon); }
+    void TaskBarInsert(Widget *handle, HICN icon, char *bubbletext) { dw_taskbar_insert(handle ? handle->GetHWND() : DW_NOHWND, icon, bubbletext); }
+    void TaskBarDelete(Widget *handle, HICN icon) { dw_taskbar_delete(handle ? handle->GetHWND() : DW_NOHWND, icon); }
 };
 
 // Static singleton reference declared outside of the class
--- a/dwtestoo.cpp	Wed Dec 28 03:28:31 2022 +0000
+++ b/dwtestoo.cpp	Wed Dec 28 09:32:27 2022 +0000
@@ -171,12 +171,11 @@
             }
             num_lines = i;
             fclose(fp);
-#if 0
+
             hscrollbar->SetRange(max_linewidth, cols);
             hscrollbar->SetPos(0);
             vscrollbar->SetRange(num_lines, rows);
             vscrollbar->SetPos(0);
-#endif
         }
 #ifdef __ANDROID__
         if(fd != -1)
@@ -414,10 +413,10 @@
 
         cursortogglebutton->ConnectClicked([this, cursortogglebutton] () -> int 
         {
-            this->cursor_arrow = !this->cursor_arrow;
             cursortogglebutton->SetText(this->cursor_arrow ? "Set Cursor pointer - ARROW" :
                                         "Set Cursor pointer - CLOCK");
             this->SetPointer(this->cursor_arrow ? DW_POINTER_CLOCK : DW_POINTER_DEFAULT);
+            this->cursor_arrow = !this->cursor_arrow;
             return FALSE;
         });
 
@@ -427,6 +426,315 @@
             return FALSE;
         });
     }
+
+    void CreateRender(DW::Box *notebookbox) {
+        int vscrollbarwidth, hscrollbarheight;
+        wchar_t widestring[100] = L"DWTest Wide";
+        char *utf8string = dw_wchar_to_utf8(widestring);
+
+        // create a box to pack into the notebook page
+        DW::Box *pagebox = new DW::Box(DW_HORZ, 2);
+        notebookbox->PackStart(pagebox, 0, 0, TRUE, TRUE, 0);
+
+        // now a status area under this box
+        DW::Box *hbox = new DW::Box(DW_HORZ, 1);
+        notebookbox->PackStart(hbox, 100, 20, TRUE, FALSE, 1);
+
+        DW::StatusText *status1 = new DW::StatusText();
+        hbox->PackStart(status1, 100, DW_SIZE_AUTO, TRUE, FALSE, 1);
+
+        DW::StatusText *status2 = new DW::StatusText();
+        hbox->PackStart(status2, 100, DW_SIZE_AUTO, TRUE, FALSE, 1);
+        // a box with combobox and button
+        hbox = new DW::Box(DW_HORZ, 1 );
+        notebookbox->PackStart(hbox, 100, 25, TRUE, FALSE, 1);
+
+        DW::ComboBox *rendcombo = new DW::ComboBox( "Shapes Double Buffered");
+        hbox->PackStart(rendcombo, 80, 25, TRUE, TRUE, 0);
+        rendcombo->Append("Shapes Double Buffered");
+        rendcombo->Append("Shapes Direct");
+        rendcombo->Append("File Display");
+
+        DW::Text *label = new DW::Text("Image X:");
+        label->SetStyle(DW_DT_VCENTER | DW_DT_CENTER);
+        hbox->PackStart(label, DW_SIZE_AUTO, 25, FALSE, TRUE, 0);
+
+        DW::SpinButton *imagexspin = new DW::SpinButton("20");
+        hbox->PackStart(imagexspin, 25, 25, TRUE, TRUE, 0);
+
+        label = new DW::Text("Y:");
+        label->SetStyle(DW_DT_VCENTER | DW_DT_CENTER);
+        hbox->PackStart(label, DW_SIZE_AUTO, 25, FALSE, TRUE, 0);
+
+        DW::SpinButton *imageyspin = new DW::SpinButton("20");
+        hbox->PackStart(imageyspin, 25, 25, TRUE, TRUE, 0);
+        imagexspin->SetLimits(2000, 0);
+        imageyspin->SetLimits(2000, 0);
+        imagexspin->SetPos(20);
+        imageyspin->SetPos(20);
+
+        DW::CheckBox *imagestretchcheck = new DW::CheckBox("Stretch");
+        hbox->PackStart(imagestretchcheck, DW_SIZE_AUTO, 25, FALSE, TRUE, 0);
+
+        DW::Button *refreshbutton = new DW::Button("Refresh");
+        hbox->PackStart(refreshbutton, DW_SIZE_AUTO, 25, FALSE, TRUE, 0);
+
+        DW::Button *printbutton = new DW::Button("Print");
+        hbox->PackStart(printbutton, DW_SIZE_AUTO, 25, FALSE, TRUE, 0);
+
+        // Pre-create the scrollbars so we can query their sizes
+        vscrollbar = new DW::ScrollBar(DW_VERT, 50);
+        hscrollbar = new DW::ScrollBar(DW_HORZ, 50);
+        vscrollbar->GetPreferredSize(&vscrollbarwidth, NULL);
+        hscrollbar->GetPreferredSize(NULL, &hscrollbarheight);
+
+        // On GTK with overlay scrollbars enabled this returns us 0...
+        // so in that case we need to give it some real values.
+        if(!vscrollbarwidth)
+            vscrollbarwidth = 8;
+        if(!hscrollbarheight)
+            hscrollbarheight = 8;
+
+        // Create render box for line number pixmap
+        DW::Render *render1 = new DW::Render();
+        render1->SetFont(FIXEDFONT);
+        render1->GetTextExtents("(g", &font_width, &font_height);
+        font_width = font_width / 2;
+
+        DW::Box *vscrollbox = new DW::Box(DW_VERT, 0);
+        vscrollbox->PackStart(render1, font_width*width1, font_height*rows, FALSE, TRUE, 0);
+        vscrollbox->PackStart(DW_NOHWND, (font_width*(width1+1)), hscrollbarheight, FALSE, FALSE, 0);
+        pagebox->PackStart(vscrollbox, 0, 0, FALSE, TRUE, 0);
+
+        // pack empty space 1 character wide
+        pagebox->PackStart(DW_NOHWND, font_width, 0, FALSE, TRUE, 0);
+
+        // create box for filecontents and horz scrollbar
+        DW::Box *textbox = new DW::Box(DW_VERT,0 );
+        pagebox->PackStart(textbox, 0, 0, TRUE, TRUE, 0);
+
+        // create render box for filecontents pixmap
+        DW::Render *render2 = new DW::Render();
+        textbox->PackStart(render2, 10, 10, TRUE, TRUE, 0);
+        render2->SetFont(FIXEDFONT);
+        // create horizonal scrollbar
+        textbox->PackStart(hscrollbar, TRUE, FALSE, 0);
+
+        // create vertical scrollbar
+        vscrollbox = new DW::Box(DW_VERT, 0);
+        vscrollbox->PackStart(vscrollbar, FALSE, TRUE, 0);
+        // Pack an area of empty space of the scrollbar dimensions
+        vscrollbox->PackStart(DW_NOHWND, vscrollbarwidth, hscrollbarheight, FALSE, FALSE, 0);
+        pagebox->PackStart(vscrollbox, 0, 0, FALSE, TRUE, 0);
+
+        pixmap1 = new DW::Pixmap(render1, font_width*width1, font_height*rows);
+        pixmap2 = new DW::Pixmap(render2, font_width*cols, font_height*rows);
+        image = new DW::Pixmap(render1, "image/test");
+        if(!image || !image->GetHPIXMAP())
+            image = new DW::Pixmap(render1, "~/test");
+        if(!image || !image->GetHPIXMAP())
+        {
+            char *appdir = app->GetDir();
+            char pathbuff[1025] = {0};
+            int pos = (int)strlen(appdir);
+            
+            strncpy(pathbuff, appdir, 1024);
+            pathbuff[pos] = DW_DIR_SEPARATOR;
+            pos++;
+            strncpy(&pathbuff[pos], "test", 1024-pos);
+            image = new DW::Pixmap(render1, pathbuff);
+        }
+        if(image)
+            image->SetTransparentColor(DW_CLR_WHITE);
+
+        app->MessageBox(utf8string ? utf8string : "DWTest", DW_MB_OK|DW_MB_INFORMATION, "Width: %d Height: %d\n", font_width, font_height);
+        if(utf8string)
+            app->Free(utf8string);
+        pixmap1->DrawRect(DW_DRAW_FILL | DW_DRAW_NOAA, 0, 0, font_width*width1, font_height*rows);
+        pixmap2->DrawRect(DW_DRAW_FILL | DW_DRAW_NOAA, 0, 0, font_width*cols, font_height*rows);
+
+        // Signal handler lambdas
+        render1->ConnectButtonPress([this](int x, int y, int buttonmask) -> int
+        {
+            DW::Menu *menu = new DW::Menu();
+            DW::MenuItem *menuitem = menu->AppendItem("~Quit");
+            long px, py;
+
+            menuitem->ConnectClicked([this] () -> int 
+            {
+                if(this->app->MessageBox(APP_TITLE, DW_MB_YESNO | DW_MB_QUESTION, APP_EXIT) != 0) {
+                    this->app->MainQuit();
+                }
+                return TRUE;
+            });
+
+
+            menu->AppendItem(DW_MENU_SEPARATOR);
+            menuitem = menu->AppendItem("~Show Window");
+            menuitem->ConnectClicked([this]() -> int
+            {
+                this->Show();
+                this->Raise();
+                return TRUE;
+            });
+
+            this->app->GetPointerPos(&px, &py);
+            menu->Popup(this, (int)px, (int)py);
+            return TRUE;
+        });
+
+        render1->ConnectExpose([this](DWExpose *exp) -> int 
+        {
+            return TRUE;
+        });
+
+        render2->ConnectExpose([this](DWExpose *exp) -> int 
+        {
+            return TRUE;
+        });
+
+        render2->ConnectKeyPress([this, status1](char ch, int vk, int state, char *utf8) -> int
+        {
+            char tmpbuf[101] = {0};
+            if(ch)
+                snprintf(tmpbuf, 100, "Key: %c(%d) Modifiers: %s(%d) utf8 %s", ch, ch, this->ResolveKeyModifiers(state), state,  utf8);
+            else
+                snprintf(tmpbuf, 100, "Key: %s(%d) Modifiers: %s(%d) utf8 %s", this->ResolveKeyName(vk), vk, ResolveKeyModifiers(state), state, utf8);
+            status1->SetText(tmpbuf);
+            return FALSE;
+        });
+
+        hscrollbar->ConnectValueChanged([this, status1](int value) -> int
+        {
+            char tmpbuf[101] = {0};
+
+            this->current_col = value;
+            snprintf(tmpbuf, 100, "Row:%d Col:%d Lines:%d Cols:%d", current_row,current_col,num_lines,max_linewidth);
+            status1->SetText(tmpbuf);
+            this->RenderDraw();
+            return TRUE;
+        });
+
+        vscrollbar->ConnectValueChanged([this, status1](int value) -> int
+        {
+            char tmpbuf[101] = {0};
+
+            this->current_row = value;
+            snprintf(tmpbuf, 100, "Row:%d Col:%d Lines:%d Cols:%d", current_row,current_col,num_lines,max_linewidth);
+            status1->SetText(tmpbuf);
+            this->RenderDraw();
+            return TRUE;
+        });
+
+        render2->ConnectMotionNotify([this, status2](int x, int y, int buttonmask) -> int
+        {
+            char buf[201] = {0};
+
+            snprintf(buf, 200, "motion_notify: %dx%d buttons %d", x, y, buttonmask);
+            status2->SetText(buf);
+            return FALSE;
+        });
+
+        render2->ConnectButtonPress([this, status2](int x, int y, int buttonmask) -> int
+        {
+            char buf[201] = {0};
+
+            snprintf(buf, 200, "button_press: %dx%d buttons %d", x, y, buttonmask);
+            status2->SetText(buf);
+            return FALSE;
+        });
+
+        render2->ConnectConfigure([this, render1, render2](int width, int height) -> int
+        {
+            DW::Pixmap *old1 = this->pixmap1, *old2 = this->pixmap2;
+
+            rows = height / font_height;
+            cols = width / font_width;
+
+            // Create new pixmaps with the current sizes
+            this->pixmap1 = new DW::Pixmap(render1, (unsigned long)(font_width*(width1)), (unsigned long)height);
+            this->pixmap2 = new DW::Pixmap(render2, (unsigned long)width, (unsigned long)height);
+
+            // Make sure the side area is cleared
+            this->pixmap1->SetForegroundColor(DW_CLR_WHITE);
+            this->pixmap1->DrawRect(DW_DRAW_FILL | DW_DRAW_NOAA, 0, 0, (int)this->pixmap1->GetWidth(), (int)this->pixmap1->GetHeight());
+
+            // Destroy the old pixmaps
+            delete old1;
+            delete old2;
+
+            // Update scrollbar ranges with new values
+            this->hscrollbar->SetRange(max_linewidth, cols);
+            this->vscrollbar->SetRange(num_lines, rows);
+
+            // Redraw the render widgets
+            this->RenderDraw();
+            return TRUE;
+        });
+
+        imagestretchcheck->ConnectClicked([this]() -> int
+        {
+            this->RenderDraw();
+            return TRUE;
+        });
+
+        refreshbutton->ConnectClicked([this]() -> int
+        {
+            this->RenderDraw();
+            return TRUE;
+        });
+
+        printbutton->ConnectClicked([this]() -> int
+        {
+#if 0 // TODO
+            DW::Print *print = new DW::Print("DWTest Job", 0, 2, [this](DW::Pixmap *pixmap, int page_num) -> int
+            {
+               pixmap->SetFont(FIXEDFONT);
+               if(page_num == 0)
+               {
+                   this->DrawShapes(FALSE, pixmap);
+               }
+               else if(page_num == 1)
+               {
+                   /* Get the font size for this printer context... */
+                   int fheight, fwidth;
+
+                   /* If we have a file to display... */
+                   if(current_file)
+                   {
+                       int nrows;
+
+                       /* Calculate new dimensions */
+                       pixmap->GetTextExtents("(g", NULL, &fheight);
+                       nrows = (int)(pixmap->GetHeight() / fheight);
+
+                       /* Do the actual drawing */
+                       this->DrawFile(0, 0, nrows, fheight, pixmap);
+                   }
+                   else
+                   {
+                       /* We don't have a file so center an error message on the page */
+                       const char *text = "No file currently selected!";
+                       int posx, posy;
+
+                       pixmap->GetTextExtents(text, &fwidth, &fheight);
+
+                       posx = (int)(pixmap->GetWidth() - fwidth)/2;
+                       posy = (int)(pixmap->GetHeight() - fheight)/2;
+
+                       pixmap->SetColor(DW_CLR_BLACK, DW_CLR_WHITE);
+                       pixmap->DrawText(posx, posy, text);
+                   }
+               }
+               return TRUE;
+            });
+            print->Run(0);
+#endif
+            return TRUE;
+        });
+
+        app->TaskBarInsert(render1, fileicon, "DWTest");
+    }
 public:
     // Constructor creates the application
     DWTest(const char *title): DW::Window(title) {
@@ -491,13 +799,20 @@
             return TRUE;
         });
 
-        // Create Notebook page 1
+        // Create Notebook Page 1 - Input
         notebookbox = new DW::Box(DW_VERT, 5);
         CreateInput(notebookbox);
         unsigned long notebookpage = notebook->PageNew(0, TRUE);
         notebook->Pack(notebookpage, notebookbox);
         notebook->PageSetText(notebookpage, "buttons and entry");
 
+        // Create Notebook Page 2 - Render
+        notebookbox = new DW::Box(DW_VERT, 5);
+        CreateRender(notebookbox);
+        notebookpage = notebook->PageNew(0, TRUE);
+        notebook->Pack(notebookpage, notebookbox);
+        notebook->PageSetText(notebookpage, "render");
+
         // Finalize the window
         this->SetSize(640, 550);
 
@@ -518,7 +833,8 @@
     unsigned long current_color;
 
     // Page 2
-    HPIXMAP text1pm,text2pm,image;
+    DW::Pixmap *pixmap1, *pixmap2, *image;
+    DW::ScrollBar *hscrollbar, *vscrollbar;
     int image_x = 20, image_y = 20, image_stretch = 0;
 
     int font_width = 8, font_height=12;
@@ -529,13 +845,13 @@
 
     FILE *fp=NULL;
     char **lp;
+    char *current_file = NULL;
 
     // Page 4
     int mle_point=-1;
 
     // Miscellaneous
-    int menu_enabled = 1;
-    char *current_file = NULL;
+    int menu_enabled = TRUE;
     HICN fileicon,foldericon;
 
     int OnDelete() override {