Refactor text window buttons to allow for more custom behavior.

This commit is contained in:
whitequark 2016-08-13 06:46:54 +00:00
parent e2e9167210
commit 8ce2922902
2 changed files with 148 additions and 98 deletions

View File

@ -5,6 +5,121 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "solvespace.h" #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<Pixmap> 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[] = { const TextWindow::Color TextWindow::fgColors[] = {
{ 'd', RGBi(255, 255, 255) }, { 'd', RGBi(255, 255, 255) },
{ 'l', RGBi(100, 100, 255) }, { 'l', RGBi(100, 100, 255) },
@ -27,23 +142,6 @@ const TextWindow::Color TextWindow::bgColors[] = {
{ 0, RGBi( 0, 0, 0) } { 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) { void TextWindow::MakeColorTable(const Color *in, float *out) {
int i; int i;
for(i = 0; in[i].c != 0; i++) { for(i = 0; in[i].c != 0; i++) {
@ -340,7 +438,7 @@ void TextWindow::Show() {
void TextWindow::TimerCallback() void TextWindow::TimerCallback()
{ {
tooltippedIcon = hoveredIcon; tooltippedButton = hoveredButton;
InvalidateText(); InvalidateText();
} }
@ -356,100 +454,58 @@ void TextWindow::DrawOrHitTestIcons(UiCanvas *uiCanvas, TextWindow::DrawOrHitHow
if(how == PAINT) { if(how == PAINT) {
int top = y - 28, bot = y + 4; int top = y - 28, bot = y + 4;
uiCanvas->DrawRect(0, width, top, bot, 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) { if(how != PAINT) {
hoveredIcon = NULL; hoveredButton = NULL;
} }
HideShowIcon *hsi; for(Button *button : buttons) {
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));
}
if(how == PAINT) { if(how == PAINT) {
uiCanvas->DrawPixmap(hsi->icon, x, y - 24); button->Draw(uiCanvas, x, y, (button == hoveredButton));
} else if(mx > x - 2 && mx < x + 26 &&
if(hsi == hoveredIcon) { my < y + 2 && my > y - 26) {
uiCanvas->DrawRect(x - 2, x + 26, y + 2, y - 26, // The mouse is hovered over this icon, so do the tooltip
/*fillColor=*/{ 255, 255, 0, 75 }, /*outlineColor=*/{}); // stuff.
if(button != tooltippedButton) {
oldMousePos = Point2d::From(mx, my);
} }
if(!*(hsi->var)) { if(button != oldHovered || how == CLICK) {
RgbaColor color = { 255, 0, 0, 150 }; SetTimerFor(1000);
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);
} }
} else { hoveredButton = button;
if(mx > x - 2 && mx < x + 26 && if(how == CLICK) {
my < y + 2 && my > y - 26) button->Click();
{
// 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);
}
} }
} }
x += 32; x += button->AdvanceWidth();
} }
if(how != PAINT && hoveredIcon != oldHovered) { if(how != PAINT && hoveredButton != oldHovered) {
InvalidateText(); InvalidateText();
} }
if(tooltippedIcon) { if(tooltippedButton && !tooltippedButton->Tooltip().empty()) {
if(how == PAINT) { if(how == PAINT) {
std::string str; std::string tooltip = tooltippedButton->Tooltip();
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);
}
int ox = (int)oldMousePos.x, oy = (int)oldMousePos.y - LINE_HEIGHT; int ox = (int)oldMousePos.x, oy = (int)oldMousePos.y - LINE_HEIGHT;
ox += 3; ox += 3;
oy -= 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); ox = min(ox, (width - 25) - tw);
oy = max(oy, 5); oy = max(oy, 5);
uiCanvas->DrawRect(ox, ox+tw, oy, oy+LINE_HEIGHT, uiCanvas->DrawRect(ox, ox+tw, oy, oy+LINE_HEIGHT,
/*fillColor=*/{ 255, 255, 150, 255 }, /*fillColor=*/{ 255, 255, 150, 255 },
/*outlineColor=*/{ 0, 0, 0, 255 }); /*outlineColor=*/{ 0, 0, 0, 255 });
uiCanvas->DrawBitmapText(str, ox+5, oy-3+LINE_HEIGHT, { 0, 0, 0, 255 }); uiCanvas->DrawBitmapText(tooltip, ox+5, oy-3+LINE_HEIGHT, { 0, 0, 0, 255 });
} else { } else {
if(!hoveredIcon || if(!hoveredButton || (hoveredButton != tooltippedButton)) {
(hoveredIcon != tooltippedIcon)) tooltippedButton = NULL;
{
tooltippedIcon = NULL;
InvalidateGraphics(); InvalidateGraphics();
} }
// And if we're hovered, then we've set a timer that will cause // And if we're hovered, then we've set a timer that will cause
@ -936,8 +992,8 @@ done:
} }
void TextWindow::MouseLeave() { void TextWindow::MouseLeave() {
tooltippedIcon = NULL; tooltippedButton = NULL;
hoveredIcon = NULL; hoveredButton = NULL;
hoveredRow = 0; hoveredRow = 0;
hoveredCol = 0; hoveredCol = 0;
InvalidateText(); InvalidateText();
@ -958,3 +1014,4 @@ void TextWindow::ScrollbarEvent(int newPos) {
} }
} }
}

View File

@ -142,6 +142,8 @@ enum class ContextCommand : uint32_t {
FIRST_STYLE = 0x40000000 FIRST_STYLE = 0x40000000
}; };
class Button;
class TextWindow { class TextWindow {
public: public:
enum { enum {
@ -194,15 +196,6 @@ public:
int rows; int rows;
// The row of icons at the top of the text window, to hide/show things // 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<Pixmap> icon;
} HideShowIcon;
static HideShowIcon hideShowIcons[];
static bool SPACER;
void Draw(Canvas *canvas); void Draw(Canvas *canvas);
// These are called by the platform-specific code. // These are called by the platform-specific code.
@ -221,7 +214,7 @@ public:
double mx, double my); double mx, double my);
void TimerCallback(); void TimerCallback();
Point2d oldMousePos; Point2d oldMousePos;
HideShowIcon *hoveredIcon, *tooltippedIcon; Button *hoveredButton, *tooltippedButton;
Vector HsvToRgb(Vector hsv); Vector HsvToRgb(Vector hsv);
std::shared_ptr<Pixmap> HsvPattern2d(int w, int h); std::shared_ptr<Pixmap> HsvPattern2d(int w, int h);