From cfcd6bd672829edfbb325e3d264570c034ccc0f1 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Sun, 9 Aug 2020 23:03:34 +0300 Subject: Closing and duplicating tabs --- src/ui/documentwidget.c | 29 ++++++-- src/ui/documentwidget.h | 9 +-- src/ui/util.c | 8 ++- src/ui/util.h | 23 +++---- src/ui/widget.c | 11 ++++ src/ui/widget.h | 1 + src/ui/window.c | 171 ++++++------------------------------------------ 7 files changed, 81 insertions(+), 171 deletions(-) (limited to 'src/ui') diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 9a97c39e..6313e6df 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c @@ -280,6 +280,11 @@ static void updateVisible_DocumentWidget_(iDocumentWidget *d) { } static void updateWindowTitle_DocumentWidget_(const iDocumentWidget *d) { + iLabelWidget *tabButton = tabPageButton_Widget(findWidget_App("doctabs"), d); + if (!tabButton) { + /* Not part of the UI at the moment. */ + return; + } iStringArray *title = iClob(new_StringArray()); if (!isEmpty_String(title_GmDocument(d->doc))) { pushBack_StringArray(title, title_GmDocument(d->doc)); @@ -298,7 +303,6 @@ static void updateWindowTitle_DocumentWidget_(const iDocumentWidget *d) { pushBackCStr_StringArray(title, "Lagrange"); } /* Take away parts if it doesn't fit. */ - iLabelWidget *tabButton = tabPageButton_Widget(findWidget_App("doctabs"), d); const int avail = bounds_Widget(as_Widget(tabButton)).size.x - 3 * gap_UI; iBool setWindow = (document_App() == d); for (;;) { @@ -455,9 +459,11 @@ static void fetch_DocumentWidget_(iDocumentWidget *d) { static void updateTrust_DocumentWidget_(iDocumentWidget *d, const iGmResponse *response) { #define openLock_CStr "\U0001f513" #define closedLock_CStr "\U0001f512" - d->certFlags = response->certFlags; - d->certExpiry = response->certValidUntil; - set_String(d->certSubject, &response->certSubject); + if (response) { + d->certFlags = response->certFlags; + d->certExpiry = response->certValidUntil; + set_String(d->certSubject, &response->certSubject); + } iLabelWidget *lock = findWidget_App("navbar.lock"); if (~d->certFlags & available_GmCertFlag) { setFlags_Widget(as_Widget(lock), disabled_WidgetFlag, iTrue); @@ -516,6 +522,16 @@ void setUrlFromCache_DocumentWidget(iDocumentWidget *d, const iString *url, iBoo } } +iDocumentWidget *duplicate_DocumentWidget(iDocumentWidget *orig) { + iDocumentWidget *d = new_DocumentWidget(); + delete_History(d->history); + d->textSizePercent = orig->textSizePercent; + d->initialScrollY = orig->scrollY; + d->history = copy_History(orig->history); + setUrlFromCache_DocumentWidget(d, orig->url, iTrue); + return d; +} + void setUrl_DocumentWidget(iDocumentWidget *d, const iString *url) { setUrlFromCache_DocumentWidget(d, url, iFalse); } @@ -754,11 +770,14 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) if (cmp_String(id_Widget(w), suffixPtr_Command(cmd, "id")) == 0) { /* Set palette for our document. */ updateTheme_DocumentWidget_(d); + updateTrust_DocumentWidget_(d, NULL); + setWidth_GmDocument(d->doc, documentWidth_DocumentWidget_(d)); + updateVisible_DocumentWidget_(d); } updateWindowTitle_DocumentWidget_(d); return iFalse; } - else if (equal_Command(cmd, "server.showcert")) { + else if (equal_Command(cmd, "server.showcert") && d == document_App()) { const char *unchecked = red_ColorEscape "\u2610"; const char *checked = green_ColorEscape "\u2611"; makeMessage_Widget( diff --git a/src/ui/documentwidget.h b/src/ui/documentwidget.h index 38fcf8e3..5e7c3f2c 100644 --- a/src/ui/documentwidget.h +++ b/src/ui/documentwidget.h @@ -7,11 +7,12 @@ iDeclareType(History) iDeclareWidgetClass(DocumentWidget) iDeclareObjectConstruction(DocumentWidget) -iHistory * history_DocumentWidget (iDocumentWidget *); +iDocumentWidget *duplicate_DocumentWidget (iDocumentWidget *); +iHistory * history_DocumentWidget (iDocumentWidget *); + +const iString * url_DocumentWidget (const iDocumentWidget *); +iBool isRequestOngoing_DocumentWidget (const iDocumentWidget *); void setUrl_DocumentWidget (iDocumentWidget *, const iString *url); void setUrlFromCache_DocumentWidget (iDocumentWidget *d, const iString *url, iBool isFromCache); void setInitialScroll_DocumentWidget (iDocumentWidget *, int scrollY); /* set after content received */ - -const iString * url_DocumentWidget (const iDocumentWidget *); -iBool isRequestOngoing_DocumentWidget (const iDocumentWidget *); diff --git a/src/ui/util.c b/src/ui/util.c index 9ac1913d..5868e9d7 100644 --- a/src/ui/util.c +++ b/src/ui/util.c @@ -195,6 +195,8 @@ iWidget *makeMenu_Widget(iWidget *parent, const iMenuItem *items, size_t n) { void openMenu_Widget(iWidget *d, iInt2 coord) { /* Menu closes when commands are emitted, so handle any pending ones beforehand. */ + postCommand_App("cancel"); /* dismiss any other menus */ + processEvents_App(postedEventsOnly_AppEventMode); setFlags_Widget(d, hidden_WidgetFlag, iFalse); arrange_Widget(d); d->rect.pos = coord; @@ -318,7 +320,7 @@ static void addTabPage_Widget_(iWidget *tabs, enum iWidgetAddPos addPos, iWidget iClob(new_LabelWidget(label, key, kmods, format_CStr("tabs.switch page:%p", page))), addPos); setFlags_Widget(button, selected_WidgetFlag, isSel); - setFlags_Widget(button, expand_WidgetFlag, iTrue); + setFlags_Widget(button, commandOnClick_WidgetFlag | expand_WidgetFlag, iTrue); addChildPos_Widget(pages, page, addPos); setFlags_Widget(page, hidden_WidgetFlag | disabled_WidgetFlag, !isSel); } @@ -388,6 +390,10 @@ iLabelWidget *tabPageButton_Widget(iWidget *tabs, const iAnyObject *page) { return tabButtonForPage_Widget_(tabs, page); } +iBool isTabButton_Widget(const iWidget *d) { + return d->parent && cmp_String(id_Widget(d->parent), "tabs.buttons") == 0; +} + void setTabPageLabel_Widget(iWidget *tabs, const iAnyObject *page, const iString *label) { iLabelWidget *button = tabButtonForPage_Widget_(tabs, page); setText_LabelWidget(button, label); diff --git a/src/ui/util.h b/src/ui/util.h index 6e210422..26066e53 100644 --- a/src/ui/util.h +++ b/src/ui/util.h @@ -94,17 +94,18 @@ iLabelWidget * makeMenuButton_LabelWidget (const char *label, const iMenuItem /*-----------------------------------------------------------------------------------------------*/ -iWidget * makeTabs_Widget (iWidget *parent); -void appendTabPage_Widget (iWidget *tabs, iWidget *page, const char *label, int key, int kmods); -void prependTabPage_Widget (iWidget *tabs, iWidget *page, const char *label, int key, int kmods); -iWidget * tabPage_Widget (iWidget *tabs, size_t index); -iLabelWidget *tabPageButton_Widget (iWidget *tabs, const iAnyObject *page); -iWidget * removeTabPage_Widget (iWidget *tabs, size_t index); /* returns the page */ -void showTabPage_Widget (iWidget *tabs, const iWidget *page); -void setTabPageLabel_Widget (iWidget *tabs, const iAnyObject *page, const iString *label); -size_t tabPageIndex_Widget (const iWidget *tabs, const iAnyObject *page); -const iWidget *currentTabPage_Widget(const iWidget *tabs); -size_t tabCount_Widget (const iWidget *tabs); +iWidget * makeTabs_Widget (iWidget *parent); +void appendTabPage_Widget (iWidget *tabs, iWidget *page, const char *label, int key, int kmods); +void prependTabPage_Widget (iWidget *tabs, iWidget *page, const char *label, int key, int kmods); +iWidget * removeTabPage_Widget (iWidget *tabs, size_t index); /* returns the page */ +void showTabPage_Widget (iWidget *tabs, const iWidget *page); +void setTabPageLabel_Widget (iWidget *tabs, const iAnyObject *page, const iString *label); +iWidget * tabPage_Widget (iWidget *tabs, size_t index); +iLabelWidget * tabPageButton_Widget (iWidget *tabs, const iAnyObject *page); +iBool isTabButton_Widget (const iWidget *); +size_t tabPageIndex_Widget (const iWidget *tabs, const iAnyObject *page); +const iWidget * currentTabPage_Widget (const iWidget *tabs); +size_t tabCount_Widget (const iWidget *tabs); /*-----------------------------------------------------------------------------------------------*/ diff --git a/src/ui/widget.c b/src/ui/widget.c index 56b05aa6..51841d64 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c @@ -419,6 +419,17 @@ iBool processEvent_Widget(iWidget *d, const SDL_Event *ev) { return iTrue; } } + else if (d->flags & commandOnClick_WidgetFlag && (ev->type == SDL_MOUSEBUTTONDOWN || + ev->type == SDL_MOUSEBUTTONUP) && + contains_Widget(d, init_I2(ev->button.x, ev->button.y))) { + postCommand_Widget(d, + "mouse.clicked arg:%d button:%d coord:%d %d", + ev->type == SDL_MOUSEBUTTONDOWN ? 1 : 0, + ev->button.button, + ev->button.x, + ev->button.y); + return iTrue; + } switch (ev->type) { case SDL_USEREVENT: { if (ev->user.code == command_UserEventCode && d->commandHandler && diff --git a/src/ui/widget.h b/src/ui/widget.h index 8277b4ba..1cea7147 100644 --- a/src/ui/widget.h +++ b/src/ui/widget.h @@ -30,6 +30,7 @@ enum iWidgetFlag { alignLeft_WidgetFlag = iBit(6), alignRight_WidgetFlag = iBit(7), frameless_WidgetFlag = iBit(8), + commandOnClick_WidgetFlag = iBit(9), drawKey_WidgetFlag = iBit(10), focusable_WidgetFlag = iBit(11), tight_WidgetFlag = iBit(31), /* smaller padding */ diff --git a/src/ui/window.c b/src/ui/window.c index bc690426..296b8d05 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -140,6 +140,16 @@ static iBool handleNavBarCommands_(iWidget *navBar, const char *cmd) { updateTextCStr_LabelWidget(findChild_Widget(navBar, "reload"), isRequestOngoing_DocumentWidget(doc) ? stopCStr_ : reloadCStr_); } + else if (equal_Command(cmd, "mouse.clicked")) { + iWidget *widget = pointer_Command(cmd); + iWidget *menu = findWidget_App("doctabs.menu"); + if (isTabButton_Widget(widget)) { + iWidget *tabs = findWidget_App("doctabs"); + showTabPage_Widget(tabs, + tabPage_Widget(tabs, childIndex_Widget(widget->parent, widget))); + openMenu_Widget(menu, coord_Command(cmd)); + } + } else if (equal_Command(cmd, "navigate.reload")) { iDocumentWidget *doc = document_Command(cmd); if (isRequestOngoing_DocumentWidget(doc)) { @@ -265,156 +275,17 @@ static void setupUserInterface_Window(iWindow *d) { addChild_Widget(searchBar, iClob(newIcon_LabelWidget(" \u2b9d ", 'g', KMOD_PRIMARY | KMOD_SHIFT, "find.prev"))); addChild_Widget(searchBar, iClob(newIcon_LabelWidget("\u2a2f", SDLK_ESCAPE, 0, "find.close"))); } - -#if 0 - iWidget *mainDiv = makeHDiv_Widget(); - setId_Widget(mainDiv, "maindiv"); - addChild_Widget(d->root, iClob(mainDiv)); - - iWidget *sidebar = makeVDiv_Widget(); - setFlags_Widget(sidebar, arrangeWidth_WidgetFlag, iTrue); - setId_Widget(sidebar, "sidebar"); - addChild_Widget(mainDiv, iClob(sidebar)); - - /* Menus. */ { -#if defined (iPlatformApple) && !defined (iPlatformIOS) - /* Use the native menus. */ - insertMenuItems_MacOS("File", fileMenuItems, iElemCount(fileMenuItems)); - insertMenuItems_MacOS("Edit", editMenuItems, iElemCount(editMenuItems)); - insertMenuItems_MacOS("View", viewMenuItems, iElemCount(viewMenuItems)); -#else - iWidget *menubar = new_Widget(); - setBackgroundColor_Widget(menubar, gray25_ColorId); - setFlags_Widget(menubar, arrangeHorizontal_WidgetFlag | arrangeHeight_WidgetFlag, iTrue); - addChild_Widget(menubar, iClob(makeMenuButton_LabelWidget("File", fileMenuItems, iElemCount(fileMenuItems)))); - addChild_Widget(menubar, iClob(makeMenuButton_LabelWidget("Edit", editMenuItems, iElemCount(editMenuItems)))); - addChild_Widget(menubar, iClob(makeMenuButton_LabelWidget("View", viewMenuItems, iElemCount(viewMenuItems)))); - addChild_Widget(sidebar, iClob(menubar)); -#endif - } - /* Tracker info. */ { - iWidget *trackerInfo = addChild_Widget(sidebar, iClob(new_Widget())); - setId_Widget(trackerInfo, "trackerinfo"); - trackerInfo->rect.size.y = lineHeight_Text(default_FontId) + 2 * gap_UI; - setFlags_Widget(trackerInfo, arrangeHorizontal_WidgetFlag | resizeChildren_WidgetFlag, iTrue); - setId_Widget( - addChild_Widget(trackerInfo, iClob(new_LabelWidget("", 'p', KMOD_PRIMARY, "pattern.goto arg:-1"))), - "trackerinfo.current"); - iLabelWidget *dims = new_LabelWidget("", 'r', KMOD_PRIMARY | KMOD_ALT, "pattern.resize"); - setId_Widget(addChild_Widget(trackerInfo, iClob(dims)), "trackerinfo.dims"); - } - - iLibraryWidget *lib = new_LibraryWidget(); - setId_Widget(as_Widget(lib), "library"); - addChildFlags_Widget(sidebar, iClob(lib), expand_WidgetFlag); - - iPlaybackWidget *play = new_PlaybackWidget(); - setId_Widget(as_Widget(play), "playback"); - addChild_Widget(sidebar, iClob(play)); - - iWidget *mainTabs = makeTabs_Widget(mainDiv); - setId_Widget(mainTabs, "maintabs"); - setFlags_Widget(mainTabs, expand_WidgetFlag, iTrue); - - /* Optional sidebar on the right. */ - iWidget *sidebar2 = new_Widget(); - setId_Widget(addChild_Widget(mainDiv, iClob(sidebar2)), "sidebar2"); - setFlags_Widget( - sidebar2, fixedWidth_WidgetFlag | frameless_WidgetFlag | resizeChildren_WidgetFlag, iTrue); - - /* Pattern sequence. */ { - iSequenceWidget *seq = new_SequenceWidget(); - appendTabPage_Widget(mainTabs, iClob(seq), "SEQUENCE", 0, 0); - } - /* Tracker. */ { - iTrackerWidget *tracker = new_TrackerWidget(); - appendTabPage_Widget(mainTabs, as_Widget(tracker), "PATTERN", 0, 0); - } - /* Voice editor. */ { - iWidget *voice = as_Widget(new_VoiceWidget()); - setId_Widget(voice, "voicelayers"); - appendTabPage_Widget(mainTabs, iClob(voice), "VOICE", '3', KMOD_PRIMARY); - } - /* Song information. */ { - iWidget *songPage = new_Widget(); - setId_Widget(songPage, "songinfo"); - setFlags_Widget(songPage, arrangeHorizontal_WidgetFlag, iTrue); - iWidget *headings = - addChildFlags_Widget(songPage, - iClob(new_Widget()), - resizeToParentHeight_WidgetFlag | resizeChildren_WidgetFlag | - arrangeVertical_WidgetFlag | arrangeWidth_WidgetFlag); - iWidget *values = addChildFlags_Widget( - songPage, iClob(new_Widget()), arrangeVertical_WidgetFlag | arrangeSize_WidgetFlag); - - setId_Widget(addChild_Widget(headings, iClob(makePadding_Widget(2 * gap_UI))), "headings.padding"); - setId_Widget(addChild_Widget(values, iClob(makePadding_Widget(2 * gap_UI))), "values.padding"); - - addChild_Widget(headings, iClob(makeHeading_Widget(cyan_ColorEscape "SONG PROPERTIES"))); - addChild_Widget(values, iClob(makeHeading_Widget(""))); - - const int fieldWidth = advance_Text(monospace_FontId, "A").x * 40; - iWidget *field; - - addChild_Widget(headings, iClob(makeHeading_Widget("Title:"))); - setId_Widget(field = addChild_Widget(values, iClob(new_InputWidget(0))), "info.title"); - field->rect.size.x = fieldWidth; - - addChild_Widget(headings, iClob(makeHeading_Widget("Author:"))); - setId_Widget(field = addChild_Widget(values, iClob(new_InputWidget(0))), "info.author"); - field->rect.size.x = fieldWidth; - - addChild_Widget(headings, iClob(makeHeading_Widget("Tempo:"))); - setId_Widget(addChild_Widget(values, iClob(new_InputWidget(3))), "info.tempo"); - - addChild_Widget(headings, iClob(makeHeading_Widget("Events per Beat:"))); - setId_Widget(addChild_Widget(values, iClob(new_InputWidget(2))), "info.eventsperbeat"); - - addChild_Widget(headings, iClob(makeHeading_Widget("Num of Tracks:"))); - setId_Widget(addChild_Widget(values, iClob(new_InputWidget(2))), "info.numtracks"); - - addChild_Widget(headings, iClob(makePadding_Widget(2 * gap_UI))); - addChild_Widget(values, iClob(makePadding_Widget(2 * gap_UI))); - - addChild_Widget(headings, iClob(makeHeading_Widget(cyan_ColorEscape "SONG METADATA"))); - addChild_Widget(values, iClob(makeHeading_Widget(""))); - - addChild_Widget(headings, iClob(makeHeading_Widget("Duration:"))); - setId_Widget(addChildFlags_Widget(values, iClob(newEmpty_LabelWidget()), - alignLeft_WidgetFlag | frameless_WidgetFlag), - "info.duration"); - addChild_Widget(headings, iClob(makeHeading_Widget("Statistics:\n\n "))); - setId_Widget(addChildFlags_Widget(values, - iClob(newEmpty_LabelWidget()), - alignLeft_WidgetFlag | frameless_WidgetFlag), - "info.statistics"); - addChild_Widget(headings, iClob(makeHeading_Widget("Created on:"))); - setId_Widget(addChildFlags_Widget(values, - iClob(newEmpty_LabelWidget()), - alignLeft_WidgetFlag | frameless_WidgetFlag), - "info.created"); - - addChild_Widget(headings, iClob(makeHeading_Widget("Last Modified on:"))); - setId_Widget(addChildFlags_Widget(values, - iClob(newEmpty_LabelWidget()), - alignLeft_WidgetFlag | frameless_WidgetFlag), - "info.lastmodified"); - /* App info in the bottom. */ { - addChildFlags_Widget(headings, iClob(new_Widget()), expand_WidgetFlag); - addChildFlags_Widget( - headings, - iClob(new_LabelWidget(gray50_ColorEscape "Version " BWH_APP_VERSION, 0, 0, NULL)), - frameless_WidgetFlag | alignLeft_WidgetFlag); - } - appendTabPage_Widget(mainTabs, iClob(songPage), "INFO", '4', KMOD_PRIMARY); - } - /* Application status. */ { - iWidget *status = addChildFlags_Widget(d->root, iClob(newEmpty_LabelWidget()), 0); - setFont_LabelWidget((iLabelWidget *) status, monospace_FontId); - setFlags_Widget(status, frameless_WidgetFlag | alignRight_WidgetFlag, iTrue); - setId_Widget(status, "status"); - } -#endif + iWidget *tabsMenu = makeMenu_Widget(d->root, + (iMenuItem[]){ + { "Close Tab", 0, 0, "tabs.close" }, + { "Duplicate Tab", 0, 0, "tabs.new duplicate:1" }, + { "---", 0, 0, NULL }, + { "Close Other Tabs", 0, 0, "tabs.close toleft:1 toright:1" }, + { "Close Tabs To Left", 0, 0, "tabs.close toleft:1" }, + { "Close Tabs To Right", 0, 0, "tabs.close toright:1" }, + }, + 6); + setId_Widget(tabsMenu, "doctabs.menu"); /* Glboal keyboard shortcuts. */ { addAction_Widget(d->root, SDLK_LEFTBRACKET, KMOD_SHIFT | KMOD_PRIMARY, "tabs.prev"); addAction_Widget(d->root, SDLK_RIGHTBRACKET, KMOD_SHIFT | KMOD_PRIMARY, "tabs.next"); -- cgit v1.2.3