summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/app.c17
-rw-r--r--src/ui/documentwidget.c3
-rw-r--r--src/ui/macos.m9
-rw-r--r--src/ui/util.c15
-rw-r--r--src/ui/util.h1
-rw-r--r--src/ui/widget.c19
-rw-r--r--src/ui/widget.h1
7 files changed, 61 insertions, 4 deletions
diff --git a/src/app.c b/src/app.c
index fa7311c6..3a1fde85 100644
--- a/src/app.c
+++ b/src/app.c
@@ -406,6 +406,23 @@ iBool handleCommand_App(const char *cmd) {
406 refresh_Widget(tabs); 406 refresh_Widget(tabs);
407 return iTrue; 407 return iTrue;
408 } 408 }
409 else if (equal_Command(cmd, "tabs.close")) {
410 iWidget *tabs = findWidget_App("doctabs");
411 if (tabCount_Widget(tabs) > 1) {
412 size_t index = tabPageIndex_Widget(tabs, document_App());
413 iWidget *closed = removeTabPage_Widget(tabs, index);
414 destroy_Widget(closed); /* released later */
415 if (index == tabCount_Widget(tabs)) {
416 index--;
417 }
418 arrange_Widget(tabs);
419 postCommandf_App("tabs.switch page:%p", tabPage_Widget(tabs, index));
420 }
421 else {
422 postCommand_App("quit");
423 }
424 return iTrue;
425 }
409 else if (equal_Command(cmd, "quit")) { 426 else if (equal_Command(cmd, "quit")) {
410 SDL_Event ev; 427 SDL_Event ev;
411 ev.type = SDL_QUIT; 428 ev.type = SDL_QUIT;
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index a789a759..53eb06bd 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -145,6 +145,9 @@ void init_DocumentWidget(iDocumentWidget *d) {
145 { "Copy", 'c', KMOD_PRIMARY, "copy" }, 145 { "Copy", 'c', KMOD_PRIMARY, "copy" },
146 { "Copy Link", 0, 0, "document.copylink" } }, 146 { "Copy Link", 0, 0, "document.copylink" } },
147 6); 147 6);
148#if !defined (iPlatformApple) /* in system menu */
149 addAction_Widget(w, SDLK_w, KMOD_PRIMARY, "tabs.close");
150#endif
148} 151}
149 152
150void deinit_DocumentWidget(iDocumentWidget *d) { 153void deinit_DocumentWidget(iDocumentWidget *d) {
diff --git a/src/ui/macos.m b/src/ui/macos.m
index bf5c2f84..dcae94e6 100644
--- a/src/ui/macos.m
+++ b/src/ui/macos.m
@@ -180,6 +180,10 @@ enum iTouchBarVariant {
180 postCommand_App("preferences"); 180 postCommand_App("preferences");
181} 181}
182 182
183- (void)closeTab {
184 postCommand_App("tabs.close");
185}
186
183- (void)postMenuItemCommand:(id)sender { 187- (void)postMenuItemCommand:(id)sender {
184 NSString *command = [menuCommands objectForKey:[(NSMenuItem *)sender title]]; 188 NSString *command = [menuCommands objectForKey:[(NSMenuItem *)sender title]];
185 if (command) { 189 if (command) {
@@ -347,6 +351,11 @@ void setupApplication_MacOS(void) {
347 NSMenuItem *prefsItem = [appMenu itemWithTitle:@"Preferences…"]; 351 NSMenuItem *prefsItem = [appMenu itemWithTitle:@"Preferences…"];
348 prefsItem.target = myDel; 352 prefsItem.target = myDel;
349 prefsItem.action = @selector(showPreferences); 353 prefsItem.action = @selector(showPreferences);
354 /* Get rid of the default window close item */
355 NSMenu *windowMenu = [[[NSApp mainMenu] itemWithTitle:@"Window"] submenu];
356 NSMenuItem *windowCloseItem = [windowMenu itemWithTitle:@"Close"];
357 windowCloseItem.target = myDel;
358 windowCloseItem.action = @selector(closeTab);
350} 359}
351 360
352void insertMenuItems_MacOS(const char *menuLabel, const iMenuItem *items, size_t count) { 361void insertMenuItems_MacOS(const char *menuLabel, const iMenuItem *items, size_t count) {
diff --git a/src/ui/util.c b/src/ui/util.c
index b0bef69e..40debd28 100644
--- a/src/ui/util.c
+++ b/src/ui/util.c
@@ -295,7 +295,11 @@ static iBool tabSwitcher_(iWidget *tabs, const char *cmd) {
295iWidget *makeTabs_Widget(iWidget *parent) { 295iWidget *makeTabs_Widget(iWidget *parent) {
296 iWidget *tabs = makeVDiv_Widget(); 296 iWidget *tabs = makeVDiv_Widget();
297 iWidget *buttons = addChild_Widget(tabs, iClob(new_Widget())); 297 iWidget *buttons = addChild_Widget(tabs, iClob(new_Widget()));
298 setFlags_Widget(buttons, arrangeHorizontal_WidgetFlag | arrangeHeight_WidgetFlag, iTrue); 298 buttons->rect.size.y = 2 * gap_UI + lineHeight_Text(default_FontId);
299 setFlags_Widget(buttons,
300 resizeChildren_WidgetFlag | arrangeHorizontal_WidgetFlag |
301 fixedHeight_WidgetFlag,
302 iTrue);
299 setId_Widget(buttons, "tabs.buttons"); 303 setId_Widget(buttons, "tabs.buttons");
300 iWidget *pages = addChildFlags_Widget( 304 iWidget *pages = addChildFlags_Widget(
301 tabs, iClob(new_Widget()), expand_WidgetFlag | resizeChildren_WidgetFlag); 305 tabs, iClob(new_Widget()), expand_WidgetFlag | resizeChildren_WidgetFlag);
@@ -313,7 +317,7 @@ static void addTabPage_Widget_(iWidget *tabs, enum iWidgetAddPos addPos, iWidget
313 findChild_Widget(tabs, "tabs.buttons"), 317 findChild_Widget(tabs, "tabs.buttons"),
314 iClob(new_LabelWidget(label, key, kmods, format_CStr("tabs.switch page:%p", page))), 318 iClob(new_LabelWidget(label, key, kmods, format_CStr("tabs.switch page:%p", page))),
315 addPos); 319 addPos);
316 setFlags_Widget(button, selected_WidgetFlag, isSel); 320 setFlags_Widget(button, selected_WidgetFlag | expand_WidgetFlag, isSel);
317 addChildPos_Widget(pages, page, addPos); 321 addChildPos_Widget(pages, page, addPos);
318 setFlags_Widget(page, hidden_WidgetFlag | disabled_WidgetFlag, !isSel); 322 setFlags_Widget(page, hidden_WidgetFlag | disabled_WidgetFlag, !isSel);
319} 323}
@@ -385,6 +389,11 @@ void setTabPageLabel_Widget(iWidget *tabs, const iAnyObject *page, const iString
385 arrange_Widget(tabs); 389 arrange_Widget(tabs);
386} 390}
387 391
392size_t tabPageIndex_Widget(const iWidget *tabs, const iAnyObject *page) {
393 iWidget *pages = findChild_Widget(tabs, "tabs.pages");
394 return childIndex_Widget(pages, page);
395}
396
388const iWidget *currentTabPage_Widget(const iWidget *tabs) { 397const iWidget *currentTabPage_Widget(const iWidget *tabs) {
389 iWidget *pages = findChild_Widget(tabs, "tabs.pages"); 398 iWidget *pages = findChild_Widget(tabs, "tabs.pages");
390 iConstForEach(ObjectList, i, pages->children) { 399 iConstForEach(ObjectList, i, pages->children) {
@@ -396,7 +405,7 @@ const iWidget *currentTabPage_Widget(const iWidget *tabs) {
396} 405}
397 406
398size_t tabCount_Widget(const iWidget *tabs) { 407size_t tabCount_Widget(const iWidget *tabs) {
399 return childCount_Widget(findChild_Widget(tabs, "tabs.buttons")); 408 return childCount_Widget(findChild_Widget(tabs, "tabs.pages"));
400} 409}
401 410
402/*-----------------------------------------------------------------------------------------------*/ 411/*-----------------------------------------------------------------------------------------------*/
diff --git a/src/ui/util.h b/src/ui/util.h
index 1f35b8e8..6eeea11d 100644
--- a/src/ui/util.h
+++ b/src/ui/util.h
@@ -101,6 +101,7 @@ iWidget * tabPage_Widget (iWidget *tabs, size_t index);
101iWidget * removeTabPage_Widget (iWidget *tabs, size_t index); /* returns the page */ 101iWidget * removeTabPage_Widget (iWidget *tabs, size_t index); /* returns the page */
102void showTabPage_Widget (iWidget *tabs, const iWidget *page); 102void showTabPage_Widget (iWidget *tabs, const iWidget *page);
103void setTabPageLabel_Widget (iWidget *tabs, const iAnyObject *page, const iString *label); 103void setTabPageLabel_Widget (iWidget *tabs, const iAnyObject *page, const iString *label);
104size_t tabPageIndex_Widget (const iWidget *tabs, const iAnyObject *page);
104const iWidget *currentTabPage_Widget(const iWidget *tabs); 105const iWidget *currentTabPage_Widget(const iWidget *tabs);
105size_t tabCount_Widget (const iWidget *tabs); 106size_t tabCount_Widget (const iWidget *tabs);
106 107
diff --git a/src/ui/widget.c b/src/ui/widget.c
index 0db8b8fd..56b05aa6 100644
--- a/src/ui/widget.c
+++ b/src/ui/widget.c
@@ -33,7 +33,12 @@ void destroyPending_Widget(void) {
33 iForEach(PtrSet, i, rootData_.pendingDestruction) { 33 iForEach(PtrSet, i, rootData_.pendingDestruction) {
34 iWidget *widget = *i.value; 34 iWidget *widget = *i.value;
35 remove_PtrSet(onTop_RootData_(), widget); 35 remove_PtrSet(onTop_RootData_(), widget);
36 iRelease(removeChild_Widget(widget->parent, widget)); 36 if (widget->parent) {
37 iRelease(removeChild_Widget(widget->parent, widget));
38 }
39 else {
40 iRelease(widget);
41 }
37 remove_PtrSetIterator(&i); 42 remove_PtrSetIterator(&i);
38 } 43 }
39} 44}
@@ -481,6 +486,7 @@ iAny *addChildFlags_Widget(iWidget *d, iAnyObject *child, int childFlags) {
481} 486}
482 487
483iAny *removeChild_Widget(iWidget *d, iAnyObject *child) { 488iAny *removeChild_Widget(iWidget *d, iAnyObject *child) {
489 iAssert(child);
484 ref_Object(child); 490 ref_Object(child);
485 iBool found = iFalse; 491 iBool found = iFalse;
486 iForEach(ObjectList, i, d->children) { 492 iForEach(ObjectList, i, d->children) {
@@ -505,6 +511,17 @@ iAny *child_Widget(iWidget *d, size_t index) {
505 return NULL; 511 return NULL;
506} 512}
507 513
514size_t childIndex_Widget(const iWidget *d, const iAnyObject *child) {
515 size_t index = 0;
516 iConstForEach(ObjectList, i, d->children) {
517 if (i.object == child) {
518 return index;
519 }
520 index++;
521 }
522 return iInvalidPos;
523}
524
508iAny *findChild_Widget(const iWidget *d, const char *id) { 525iAny *findChild_Widget(const iWidget *d, const char *id) {
509 if (cmp_String(id_Widget(d), id) == 0) { 526 if (cmp_String(id_Widget(d), id) == 0) {
510 return iConstCast(iAny *, d); 527 return iConstCast(iAny *, d);
diff --git a/src/ui/widget.h b/src/ui/widget.h
index 0aff6505..8277b4ba 100644
--- a/src/ui/widget.h
+++ b/src/ui/widget.h
@@ -128,6 +128,7 @@ iAny * addChildPos_Widget (iWidget *, iAnyObject *child, enum iWidgetAddPos ad
128iAny * addChildFlags_Widget(iWidget *, iAnyObject *child, int childFlags); /* holds a ref */ 128iAny * addChildFlags_Widget(iWidget *, iAnyObject *child, int childFlags); /* holds a ref */
129iAny * removeChild_Widget (iWidget *, iAnyObject *child); /* returns a ref */ 129iAny * removeChild_Widget (iWidget *, iAnyObject *child); /* returns a ref */
130iAny * child_Widget (iWidget *, size_t index); /* O(n) */ 130iAny * child_Widget (iWidget *, size_t index); /* O(n) */
131size_t childIndex_Widget (const iWidget *, const iAnyObject *child); /* O(n) */
131void arrange_Widget (iWidget *); 132void arrange_Widget (iWidget *);
132iBool dispatchEvent_Widget(iWidget *, const SDL_Event *); 133iBool dispatchEvent_Widget(iWidget *, const SDL_Event *);
133iBool processEvent_Widget (iWidget *, const SDL_Event *); 134iBool processEvent_Widget (iWidget *, const SDL_Event *);