From 61ce76bde91aaa6a5267e88577e10115f9627e5f Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Thu, 13 Aug 2020 07:42:26 +0300 Subject: Toggle sidebar visibility; save width and mode --- src/app.c | 8 +++- src/gmdocument.c | 4 ++ src/gmdocument.h | 1 + src/ui/documentwidget.c | 15 ++++--- src/ui/sidebarwidget.c | 115 +++++++++++++++++++++++++++++++----------------- src/ui/sidebarwidget.h | 4 +- src/ui/widget.c | 4 +- src/ui/window.c | 8 ++++ 8 files changed, 110 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/app.c b/src/app.c index 92e303b5..12f3393c 100644 --- a/src/app.c +++ b/src/app.c @@ -8,6 +8,7 @@ #include "ui/window.h" #include "ui/inputwidget.h" #include "ui/labelwidget.h" +#include "ui/sidebarwidget.h" #include "ui/documentwidget.h" #include "ui/util.h" #include "ui/text.h" @@ -90,13 +91,18 @@ const iString *dateStr_(const iDate *date) { static iString *serializePrefs_App_(const iApp *d) { iString *str = new_String(); - iWindow *win = get_Window(); + const iSidebarWidget *sidebar = findWidget_App("sidebar"); if (d->retainWindowSize) { int w, h, x, y; SDL_GetWindowSize(d->window->win, &w, &h); SDL_GetWindowPosition(d->window->win, &x, &y); appendFormat_String(str, "restorewindow width:%d height:%d coord:%d %d\n", w, h, x, y); + appendFormat_String(str, "sidebar.width arg:%d\n", width_SidebarWidget(sidebar)); } + if (isVisible_Widget(constAs_Widget(sidebar))) { + appendCStr_String(str, "sidebar.toggle\n"); + } + appendFormat_String(str, "sidebar.mode arg:%d\n", mode_SidebarWidget(sidebar)); appendFormat_String(str, "uiscale arg:%f\n", uiScale_Window(d->window)); return str; } diff --git a/src/gmdocument.c b/src/gmdocument.c index 3fa4a32a..ed1d1cae 100644 --- a/src/gmdocument.c +++ b/src/gmdocument.c @@ -907,6 +907,10 @@ const iArray *headings_GmDocument(const iGmDocument *d) { return &d->headings; } +const iString *source_GmDocument(const iGmDocument *d) { + return &d->source; +} + iRangecc findText_GmDocument(const iGmDocument *d, const iString *text, const char *start) { const char * src = constBegin_String(&d->source); const size_t startPos = (start ? start - src : 0); diff --git a/src/gmdocument.h b/src/gmdocument.h index fd5882bf..9f4bc1ca 100644 --- a/src/gmdocument.h +++ b/src/gmdocument.h @@ -86,6 +86,7 @@ void render_GmDocument (const iGmDocument *, iRangei visRan iInt2 size_GmDocument (const iGmDocument *); iBool hasSiteBanner_GmDocument (const iGmDocument *); const iArray * headings_GmDocument (const iGmDocument *); +const iString * source_GmDocument (const iGmDocument *); iRangecc findText_GmDocument (const iGmDocument *, const iString *text, const char *start); iRangecc findTextBefore_GmDocument (const iGmDocument *, const iString *text, const char *before); diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 483dc983..11b92e63 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c @@ -887,17 +887,22 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) : "Not trusted")); return iTrue; } - else if (equal_Command(cmd, "copy")) { + else if (equal_Command(cmd, "copy") && document_App() == d) { + iString *copied; if (d->selectMark.start) { iRangecc mark = d->selectMark; if (mark.start > mark.end) { iSwap(const char *, mark.start, mark.end); } - iString *copied = newRange_String(mark); - SDL_SetClipboardText(cstr_String(copied)); - delete_String(copied); - return iTrue; + copied = newRange_String(mark); + } + else { + /* Full document. */ + copied = copy_String(source_GmDocument(d->doc)); } + SDL_SetClipboardText(cstr_String(copied)); + delete_String(copied); + return iTrue; } else if (equalWidget_Command(cmd, w, "document.copylink")) { if (d->hoverLink) { diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c index 8ca2e448..a5e0e4ee 100644 --- a/src/ui/sidebarwidget.c +++ b/src/ui/sidebarwidget.c @@ -46,6 +46,7 @@ struct Impl_SidebarWidget { enum iSidebarMode mode; iScrollWidget *scroll; int scrollY; + int width; iLabelWidget *modeButtons[max_SidebarMode]; int itemHeight; int maxButtonLabelWidth; @@ -131,6 +132,14 @@ void setMode_SidebarWidget(iSidebarWidget *d, enum iSidebarMode mode) { d->itemHeight = heights[mode] * lineHeight_Text(default_FontId); } +enum iSidebarMode mode_SidebarWidget(const iSidebarWidget *d) { + return d->mode; +} + +int width_SidebarWidget(const iSidebarWidget *d) { + return d->width; +} + static const char *normalModeLabels_[max_SidebarMode] = { "\U0001f5b9 Outline", "\U0001f588 Bookmarks", @@ -148,11 +157,15 @@ static const char *tightModeLabels_[max_SidebarMode] = { void init_SidebarWidget(iSidebarWidget *d) { iWidget *w = as_Widget(d); init_Widget(w); + setId_Widget(w, "sidebar"); setBackgroundColor_Widget(w, none_ColorId); - setFlags_Widget(w, hover_WidgetFlag | arrangeHorizontal_WidgetFlag | resizeWidthOfChildren_WidgetFlag, iTrue); + setFlags_Widget(w, + hidden_WidgetFlag | hover_WidgetFlag | arrangeHorizontal_WidgetFlag | + resizeWidthOfChildren_WidgetFlag | collapse_WidgetFlag, + iTrue); d->scrollY = 0; - d->mode = -1; - w->rect.size.x = 75 * gap_UI; + d->mode = -1; + d->width = 75 * gap_UI; init_Array(&d->items, sizeof(iSidebarItem)); d->hoverItem = iInvalidPos; init_Click(&d->click, d, SDL_BUTTON_LEFT); @@ -165,7 +178,8 @@ void init_SidebarWidget(iSidebarWidget *d) { new_LabelWidget(normalModeLabels_[i], 0, 0, format_CStr("sidebar.mode arg:%d", i))), frameless_WidgetFlag | expand_WidgetFlag); d->maxButtonLabelWidth = - iMaxi(d->maxButtonLabelWidth, 3 * gap_UI + measure_Text(default_FontId, normalModeLabels_[i]).x); + iMaxi(d->maxButtonLabelWidth, + 3 * gap_UI + measure_Text(default_FontId, normalModeLabels_[i]).x); } addChild_Widget(w, iClob(d->scroll = new_ScrollWidget())); setThumb_ScrollWidget(d->scroll, 0, 0); @@ -245,6 +259,21 @@ static void checkModeButtonLayout_SidebarWidget_(iSidebarWidget *d) { } } +void setWidth_SidebarWidget(iSidebarWidget *d, int width) { + iWidget *w = as_Widget(d); + width = iMax(30 * gap_UI, width); + d->width = width; + if (isVisible_Widget(w)) { + w->rect.size.x = width; + } + arrange_Widget(findWidget_App("doctabs")); + checkModeButtonLayout_SidebarWidget_(d); + if (!isRefreshPending_App()) { + updateSize_DocumentWidget(document_App()); + refresh_Widget(w); + } +} + static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) { iWidget *w = as_Widget(d); /* Handle commands. */ @@ -252,51 +281,57 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) updateVisible_SidebarWidget_(d); checkModeButtonLayout_SidebarWidget_(d); } - else if (isCommand_Widget(w, ev, "mouse.clicked")) { + else if (ev->type == SDL_USEREVENT && ev->user.code == command_UserEventCode) { const char *cmd = command_UserEvent(ev); - if (argLabel_Command(cmd, "button") == SDL_BUTTON_LEFT) { - if (arg_Command(cmd)) { - setFlags_Widget(d->resizer, pressed_WidgetFlag, iTrue); - setBackgroundColor_Widget(d->resizer, gray75_ColorId); - setMouseGrab_Widget(d->resizer); - refresh_Widget(d->resizer); - } - else { - setFlags_Widget(d->resizer, pressed_WidgetFlag, iFalse); - setBackgroundColor_Widget(d->resizer, none_ColorId); - setMouseGrab_Widget(NULL); - refresh_Widget(d->resizer); + if (isCommand_Widget(w, ev, "mouse.clicked")) { + if (argLabel_Command(cmd, "button") == SDL_BUTTON_LEFT) { + if (arg_Command(cmd)) { + setFlags_Widget(d->resizer, pressed_WidgetFlag, iTrue); + setBackgroundColor_Widget(d->resizer, gray75_ColorId); + setMouseGrab_Widget(d->resizer); + refresh_Widget(d->resizer); + } + else { + setFlags_Widget(d->resizer, pressed_WidgetFlag, iFalse); + setBackgroundColor_Widget(d->resizer, none_ColorId); + setMouseGrab_Widget(NULL); + refresh_Widget(d->resizer); + } } + return iTrue; } - return iTrue; - } - else if (isCommand_Widget(w, ev, "mouse.moved")) { - const char *cmd = command_UserEvent(ev); - if (isResizing_SidebarWidget_(d)) { - const iInt2 local = localCoord_Widget(w, coord_Command(cmd)); - w->rect.size.x = iMax(30 * gap_UI, local.x + d->resizer->rect.size.x / 2); - arrange_Widget(findWidget_App("doctabs")); - checkModeButtonLayout_SidebarWidget_(d); - if (!isRefreshPending_App()) { - updateSize_DocumentWidget(document_App()); - refresh_Widget(w); + else if (isCommand_Widget(w, ev, "mouse.moved")) { + if (isResizing_SidebarWidget_(d)) { + const iInt2 local = localCoord_Widget(w, coord_Command(cmd)); + setWidth_SidebarWidget(d, local.x + d->resizer->rect.size.x / 2); } + return iTrue; } - return iTrue; - } - else if (isCommand_Widget(w, ev, "scroll.moved")) { - d->scrollY = arg_Command(command_UserEvent(ev)); - d->hoverItem = iInvalidPos; - refresh_Widget(w); - return iTrue; - } - else if (ev->type == SDL_USEREVENT && ev->user.code == command_UserEventCode) { - const char *cmd = command_UserEvent(ev); - if (isCommand_Widget(w, ev, "sidebar.mode")) { + else if (equal_Command(cmd, "sidebar.width")) { + setWidth_SidebarWidget(d, arg_Command(cmd)); + return iTrue; + } + else if (equal_Command(cmd, "sidebar.mode")) { setMode_SidebarWidget(d, arg_Command(cmd)); updateItems_SidebarWidget_(d); return iTrue; } + else if (equal_Command(cmd, "sidebar.toggle")) { + setFlags_Widget(w, hidden_WidgetFlag, isVisible_Widget(w)); + if (isVisible_Widget(w)) { + w->rect.size.x = d->width; + } + arrange_Widget(w->parent); + updateSize_DocumentWidget(document_App()); + refresh_Widget(w->parent); + return iTrue; + } + else if (equal_Command(cmd, "scroll.moved")) { + d->scrollY = arg_Command(command_UserEvent(ev)); + d->hoverItem = iInvalidPos; + refresh_Widget(w); + return iTrue; + } else if (equal_Command(cmd, "tabs.changed") || equal_Command(cmd, "document.changed")) { updateItems_SidebarWidget_(d); } diff --git a/src/ui/sidebarwidget.h b/src/ui/sidebarwidget.h index 80f22fca..4d002eee 100644 --- a/src/ui/sidebarwidget.h +++ b/src/ui/sidebarwidget.h @@ -15,4 +15,6 @@ iDeclareObjectConstruction(SidebarWidget) void setMode_SidebarWidget (iSidebarWidget *, enum iSidebarMode mode); -enum iSidebarMode mode_SidebarWidget(const iSidebarWidget *); +enum iSidebarMode mode_SidebarWidget (const iSidebarWidget *); +int width_SidebarWidget (const iSidebarWidget *); +void setWidth_SidebarWidget (iSidebarWidget *, int width); diff --git a/src/ui/widget.c b/src/ui/widget.c index 2a889683..07f1f17d 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c @@ -149,13 +149,13 @@ static int widestChild_Widget_(const iWidget *d) { } static void setWidth_Widget_(iWidget *d, int width) { - if (~d->flags & fixedWidth_WidgetFlag) { + if (~d->flags & fixedWidth_WidgetFlag || d->flags & collapse_WidgetFlag) { d->rect.size.x = width; } } static void setHeight_Widget_(iWidget *d, int height) { - if (~d->flags & fixedHeight_WidgetFlag) { + if (~d->flags & fixedHeight_WidgetFlag || d->flags & collapse_WidgetFlag) { d->rect.size.y = height; } } diff --git a/src/ui/window.c b/src/ui/window.c index 3a6b6e30..599044aa 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -71,6 +71,10 @@ static const iMenuItem navMenuItems[] = { { "New Tab", 't', KMOD_PRIMARY, "tabs.new" }, { "Open Location...", SDLK_l, KMOD_PRIMARY, "focus.set id:url" }, { "---", 0, 0, NULL }, + { "Copy Source Text", SDLK_c, KMOD_PRIMARY, "copy" }, + { "---", 0, 0, NULL }, + { "Toggle Sidebar", SDLK_s, KMOD_PRIMARY | KMOD_ALT, "sidebar.toggle" }, + { "---", 0, 0, NULL }, { "Preferences...", SDLK_COMMA, KMOD_PRIMARY, "preferences" }, { "---", 0, 0, NULL }, { "Quit Lagrange", 'q', KMOD_PRIMARY, "quit" } @@ -85,9 +89,11 @@ static const iMenuItem fileMenuItems[] = { }; static const iMenuItem editMenuItems[] = { + { "Copy Source Text", SDLK_c, KMOD_PRIMARY, "copy" }, }; static const iMenuItem viewMenuItems[] = { + { "Toggle Sidebar", SDLK_s, KMOD_PRIMARY | KMOD_ALT, "sidebar.toggle" }, }; #endif @@ -265,6 +271,8 @@ static void setupUserInterface_Window(iWindow *d) { addChild_Widget(navBar, iClob(navMenu)); #else insertMenuItems_MacOS("File", fileMenuItems, iElemCount(fileMenuItems)); + insertMenuItems_MacOS("Edit", editMenuItems, iElemCount(editMenuItems)); + insertMenuItems_MacOS("View", viewMenuItems, iElemCount(viewMenuItems)); #endif } /* Tab bar. */ { -- cgit v1.2.3