From 8ce2922902fb8d35cdf4088cb10c86e756da8883 Mon Sep 17 00:00:00 2001 From: whitequark Date: Sat, 13 Aug 2016 06:46:54 +0000 Subject: [PATCH] Refactor text window buttons to allow for more custom behavior. --- src/textwin.cpp | 233 ++++++++++++++++++++++++++++++------------------ src/ui.h | 13 +-- 2 files changed, 148 insertions(+), 98 deletions(-) diff --git a/src/textwin.cpp b/src/textwin.cpp index 56c54b0..1f37a2b 100644 --- a/src/textwin.cpp +++ b/src/textwin.cpp @@ -5,6 +5,121 @@ //----------------------------------------------------------------------------- #include "solvespace.h" +namespace SolveSpace { + +class Button { +public: + virtual std::string Tooltip() = 0; + virtual void Draw(UiCanvas *uiCanvas, int x, int y, bool asHovered) = 0; + virtual int AdvanceWidth() = 0; + virtual void Click() = 0; +}; + +class SpacerButton : public Button { +public: + std::string Tooltip() override { return ""; } + + void Draw(UiCanvas *uiCanvas, int x, int y, bool asHovered) override { + // Draw a darker-grey spacer in between the groups of icons. + uiCanvas->DrawRect(x, x + 4, y, y - 24, + /*fillColor=*/{ 45, 45, 45, 255 }, + /*outlineColor=*/{}); + } + + int AdvanceWidth() override { return 12; } + + void Click() override {} +}; + +class ShowHideButton : public Button { +public: + bool *variable; + std::string tooltip; + std::string iconName; + std::shared_ptr icon; + + ShowHideButton(bool *variable, std::string iconName, std::string tooltip) + : variable(variable), tooltip(tooltip), iconName(iconName) {} + + std::string Tooltip() override { + return ((*variable) ? "Hide " : "Show ") + tooltip; + } + + void Draw(UiCanvas *uiCanvas, int x, int y, bool asHovered) override { + if(icon == NULL) { + icon = LoadPng("icons/text-window/" + iconName + ".png"); + } + + uiCanvas->DrawPixmap(icon, x, y - 24); + if(asHovered) { + uiCanvas->DrawRect(x - 2, x + 26, y + 2, y - 26, + /*fillColor=*/{ 255, 255, 0, 75 }, + /*outlineColor=*/{}); + } + if(!*(variable)) { + int s = 0, f = 24; + RgbaColor color = { 255, 0, 0, 150 }; + uiCanvas->DrawLine(x+s, y-s, x+f, y-f, color, 2); + uiCanvas->DrawLine(x+s, y-f, x+f, y-s, color, 2); + } + } + + int AdvanceWidth() override { return 32; } + + void Click() override { SS.GW.ToggleBool(variable); } +}; + +class FacesButton : public ShowHideButton { +public: + FacesButton() + : ShowHideButton(&(SS.GW.showFaces), "faces", "") {} + + std::string Tooltip() override { + if(*variable) { + return "Don't make faces selectable with mouse"; + } else { + return "Make faces selectable with mouse"; + } + } +}; + +static SpacerButton spacerButton; + +static ShowHideButton workplanesButton = + { &(SS.GW.showWorkplanes), "workplane", "workplanes from inactive groups" }; +static ShowHideButton normalsButton = + { &(SS.GW.showNormals), "normal", "normals" }; +static ShowHideButton pointsButton = + { &(SS.GW.showPoints), "point", "points" }; +static ShowHideButton constraintsButton = + { &(SS.GW.showConstraints), "constraint", "constraints and dimensions" }; +static FacesButton facesButton; +static ShowHideButton shadedButton = + { &(SS.GW.showShaded), "shaded", "shaded view of solid model" }; +static ShowHideButton edgesButton = + { &(SS.GW.showEdges), "edges", "edges of solid model" }; +static ShowHideButton outlinesButton = + { &(SS.GW.showOutlines), "outlines", "outline of solid model" }; +static ShowHideButton meshButton = + { &(SS.GW.showMesh), "mesh", "triangle mesh of solid model" }; +static ShowHideButton hdnLinesButton = + { &(SS.GW.showHdnLines), "hidden-lines", "hidden lines" }; + +static Button *buttons[] = { + &workplanesButton, + &normalsButton, + &pointsButton, + &constraintsButton, + &facesButton, + &spacerButton, + &shadedButton, + &edgesButton, + &outlinesButton, + &meshButton, + &spacerButton, + &hdnLinesButton, +}; + const TextWindow::Color TextWindow::fgColors[] = { { 'd', RGBi(255, 255, 255) }, { 'l', RGBi(100, 100, 255) }, @@ -27,23 +142,6 @@ const TextWindow::Color TextWindow::bgColors[] = { { 0, RGBi( 0, 0, 0) } }; -bool TextWindow::SPACER = false; -TextWindow::HideShowIcon TextWindow::hideShowIcons[] = { - { &(SS.GW.showWorkplanes), "workplane", "workplanes from inactive groups", {} }, - { &(SS.GW.showNormals), "normal", "normals", {} }, - { &(SS.GW.showPoints), "point", "points", {} }, - { &(SS.GW.showConstraints), "constraint", "constraints and dimensions", {} }, - { &(SS.GW.showFaces), "faces", "XXX - special cased", {} }, - { &SPACER, 0, 0, {} }, - { &(SS.GW.showShaded), "shaded", "shaded view of solid model", {} }, - { &(SS.GW.showEdges), "edges", "edges of solid model", {} }, - { &(SS.GW.showOutlines), "outlines", "outline of solid model", {} }, - { &(SS.GW.showMesh), "mesh", "triangle mesh of solid model", {} }, - { &SPACER, 0, 0, {} }, - { &(SS.GW.showHdnLines), "hidden-lines", "hidden lines", {} }, - { 0, 0, 0, {} } -}; - void TextWindow::MakeColorTable(const Color *in, float *out) { int i; for(i = 0; in[i].c != 0; i++) { @@ -340,7 +438,7 @@ void TextWindow::Show() { void TextWindow::TimerCallback() { - tooltippedIcon = hoveredIcon; + tooltippedButton = hoveredButton; InvalidateText(); } @@ -356,100 +454,58 @@ void TextWindow::DrawOrHitTestIcons(UiCanvas *uiCanvas, TextWindow::DrawOrHitHow if(how == PAINT) { int top = y - 28, bot = y + 4; uiCanvas->DrawRect(0, width, top, bot, - /*fillColor=*/{ 30, 30, 30, 255 }, /*outlineColor=*/{}); + /*fillColor=*/{ 30, 30, 30, 255 }, /*outlineColor=*/{}); } - HideShowIcon *oldHovered = hoveredIcon; + Button *oldHovered = hoveredButton; if(how != PAINT) { - hoveredIcon = NULL; + hoveredButton = NULL; } - HideShowIcon *hsi; - for(hsi = &(hideShowIcons[0]); hsi->var; hsi++) { - if(hsi->var == &SPACER) { - // Draw a darker-grey spacer in between the groups of icons. - if(how == PAINT) { - uiCanvas->DrawRect(x, x + 4, y, y - 24, - /*fillColor=*/{ 45, 45, 45, 255 }, /*outlineColor=*/{}); - } - x += 12; - continue; - } - - if(hsi->icon == nullptr) { - hsi->icon = LoadPng(ssprintf("icons/text-window/%s.png", hsi->iconName)); - } - + for(Button *button : buttons) { if(how == PAINT) { - uiCanvas->DrawPixmap(hsi->icon, x, y - 24); - - if(hsi == hoveredIcon) { - uiCanvas->DrawRect(x - 2, x + 26, y + 2, y - 26, - /*fillColor=*/{ 255, 255, 0, 75 }, /*outlineColor=*/{}); + button->Draw(uiCanvas, x, y, (button == hoveredButton)); + } else if(mx > x - 2 && mx < x + 26 && + my < y + 2 && my > y - 26) { + // The mouse is hovered over this icon, so do the tooltip + // stuff. + if(button != tooltippedButton) { + oldMousePos = Point2d::From(mx, my); } - if(!*(hsi->var)) { - RgbaColor color = { 255, 0, 0, 150 }; - int s = 0, f = 24; - uiCanvas->DrawLine(x+s, y-s, x+f, y-f, color, 2); - uiCanvas->DrawLine(x+s, y-f, x+f, y-s, color, 2); + if(button != oldHovered || how == CLICK) { + SetTimerFor(1000); } - } else { - if(mx > x - 2 && mx < x + 26 && - my < y + 2 && my > y - 26) - { - // The mouse is hovered over this icon, so do the tooltip - // stuff. - if(hsi != tooltippedIcon) { - oldMousePos = Point2d::From(mx, my); - } - if(hsi != oldHovered || how == CLICK) { - SetTimerFor(1000); - } - hoveredIcon = hsi; - if(how == CLICK) { - SS.GW.ToggleBool(hsi->var); - } + hoveredButton = button; + if(how == CLICK) { + button->Click(); } } - x += 32; + x += button->AdvanceWidth(); } - if(how != PAINT && hoveredIcon != oldHovered) { + if(how != PAINT && hoveredButton != oldHovered) { InvalidateText(); } - if(tooltippedIcon) { + if(tooltippedButton && !tooltippedButton->Tooltip().empty()) { if(how == PAINT) { - std::string str; - - if(tooltippedIcon->var == &(SS.GW.showFaces)) { - if(SS.GW.showFaces) { - str = "Don't make faces selectable with mouse"; - } else { - str = "Make faces selectable with mouse"; - } - } else { - str = ssprintf("%s %s", *(tooltippedIcon->var) ? "Hide" : "Show", - tooltippedIcon->tip); - } + std::string tooltip = tooltippedButton->Tooltip(); int ox = (int)oldMousePos.x, oy = (int)oldMousePos.y - LINE_HEIGHT; ox += 3; oy -= 3; - int tw = (str.length() + 1) * (CHAR_WIDTH - 1); + int tw = (tooltip.length() + 1) * (CHAR_WIDTH - 1); ox = min(ox, (width - 25) - tw); oy = max(oy, 5); uiCanvas->DrawRect(ox, ox+tw, oy, oy+LINE_HEIGHT, - /*fillColor=*/{ 255, 255, 150, 255 }, - /*outlineColor=*/{ 0, 0, 0, 255 }); - uiCanvas->DrawBitmapText(str, ox+5, oy-3+LINE_HEIGHT, { 0, 0, 0, 255 }); + /*fillColor=*/{ 255, 255, 150, 255 }, + /*outlineColor=*/{ 0, 0, 0, 255 }); + uiCanvas->DrawBitmapText(tooltip, ox+5, oy-3+LINE_HEIGHT, { 0, 0, 0, 255 }); } else { - if(!hoveredIcon || - (hoveredIcon != tooltippedIcon)) - { - tooltippedIcon = NULL; + if(!hoveredButton || (hoveredButton != tooltippedButton)) { + tooltippedButton = NULL; InvalidateGraphics(); } // And if we're hovered, then we've set a timer that will cause @@ -936,8 +992,8 @@ done: } void TextWindow::MouseLeave() { - tooltippedIcon = NULL; - hoveredIcon = NULL; + tooltippedButton = NULL; + hoveredButton = NULL; hoveredRow = 0; hoveredCol = 0; InvalidateText(); @@ -958,3 +1014,4 @@ void TextWindow::ScrollbarEvent(int newPos) { } } +} diff --git a/src/ui.h b/src/ui.h index 638be2f..1e2c944 100644 --- a/src/ui.h +++ b/src/ui.h @@ -142,6 +142,8 @@ enum class ContextCommand : uint32_t { FIRST_STYLE = 0x40000000 }; +class Button; + class TextWindow { public: enum { @@ -194,15 +196,6 @@ public: int rows; // The row of icons at the top of the text window, to hide/show things - typedef struct { - bool *var; - const char *iconName; - const char *tip; - std::shared_ptr icon; - } HideShowIcon; - static HideShowIcon hideShowIcons[]; - static bool SPACER; - void Draw(Canvas *canvas); // These are called by the platform-specific code. @@ -221,7 +214,7 @@ public: double mx, double my); void TimerCallback(); Point2d oldMousePos; - HideShowIcon *hoveredIcon, *tooltippedIcon; + Button *hoveredButton, *tooltippedButton; Vector HsvToRgb(Vector hsv); std::shared_ptr HsvPattern2d(int w, int h);