summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/app.c33
-rw-r--r--src/history.c19
-rw-r--r--src/history.h2
-rw-r--r--src/ui/documentwidget.c29
-rw-r--r--src/ui/documentwidget.h9
-rw-r--r--src/ui/util.c8
-rw-r--r--src/ui/util.h23
-rw-r--r--src/ui/widget.c11
-rw-r--r--src/ui/widget.h1
-rw-r--r--src/ui/window.c171
10 files changed, 132 insertions, 174 deletions
diff --git a/src/app.c b/src/app.c
index 3a1fde85..cc8dfaff 100644
--- a/src/app.c
+++ b/src/app.c
@@ -396,20 +396,47 @@ iBool handleCommand_App(const char *cmd) {
396 iWidget *tabs = findWidget_App("doctabs"); 396 iWidget *tabs = findWidget_App("doctabs");
397 iWidget *newTabButton = findChild_Widget(tabs, "newtab"); 397 iWidget *newTabButton = findChild_Widget(tabs, "newtab");
398 removeChild_Widget(newTabButton->parent, newTabButton); 398 removeChild_Widget(newTabButton->parent, newTabButton);
399 iDocumentWidget *newDoc = new_DocumentWidget(); 399 iDocumentWidget *newDoc;
400 const iBool isDuplicate = (argLabel_Command(cmd, "duplicate") != 0);
401 if (isDuplicate) {
402 newDoc = duplicate_DocumentWidget(document_App());
403 }
404 else {
405 newDoc = new_DocumentWidget();
406 }
400 setId_Widget(as_Widget(newDoc), format_CStr("document%03d", tabCount_Widget(tabs))); 407 setId_Widget(as_Widget(newDoc), format_CStr("document%03d", tabCount_Widget(tabs)));
401 appendTabPage_Widget(tabs, iClob(newDoc), "", 0, 0); 408 appendTabPage_Widget(tabs, iClob(newDoc), "", 0, 0);
402 addChild_Widget(findChild_Widget(tabs, "tabs.buttons"), iClob(newTabButton)); 409 addChild_Widget(findChild_Widget(tabs, "tabs.buttons"), iClob(newTabButton));
403 postCommandf_App("tabs.switch page:%p", newDoc); 410 postCommandf_App("tabs.switch page:%p", newDoc);
404 postCommand_App("navigate.home"); 411 if (!isDuplicate) {
412 postCommand_App("navigate.home");
413 }
405 arrange_Widget(tabs); 414 arrange_Widget(tabs);
406 refresh_Widget(tabs); 415 refresh_Widget(tabs);
407 return iTrue; 416 return iTrue;
408 } 417 }
409 else if (equal_Command(cmd, "tabs.close")) { 418 else if (equal_Command(cmd, "tabs.close")) {
410 iWidget *tabs = findWidget_App("doctabs"); 419 iWidget *tabs = findWidget_App("doctabs");
420 size_t index = tabPageIndex_Widget(tabs, document_App());
421 iBool wasClosed = iFalse;
422 if (argLabel_Command(cmd, "toright")) {
423 while (tabCount_Widget(tabs) > index + 1) {
424 destroy_Widget(removeTabPage_Widget(tabs, index + 1));
425 }
426 wasClosed = iTrue;
427 }
428 if (argLabel_Command(cmd, "toleft")) {
429 while (index-- > 0) {
430 destroy_Widget(removeTabPage_Widget(tabs, 0));
431 }
432 postCommandf_App("tabs.switch page:%p", tabPage_Widget(tabs, 0));
433 wasClosed = iTrue;
434 }
435 if (wasClosed) {
436 arrange_Widget(tabs);
437 return iTrue;
438 }
411 if (tabCount_Widget(tabs) > 1) { 439 if (tabCount_Widget(tabs) > 1) {
412 size_t index = tabPageIndex_Widget(tabs, document_App());
413 iWidget *closed = removeTabPage_Widget(tabs, index); 440 iWidget *closed = removeTabPage_Widget(tabs, index);
414 destroy_Widget(closed); /* released later */ 441 destroy_Widget(closed); /* released later */
415 if (index == tabCount_Widget(tabs)) { 442 if (index == tabCount_Widget(tabs)) {
diff --git a/src/history.c b/src/history.c
index c009f484..5be24608 100644
--- a/src/history.c
+++ b/src/history.c
@@ -17,6 +17,16 @@ void deinit_RecentUrl(iRecentUrl *d) {
17 delete_GmResponse(d->cachedResponse); 17 delete_GmResponse(d->cachedResponse);
18} 18}
19 19
20iDefineTypeConstruction(RecentUrl)
21
22iRecentUrl *copy_RecentUrl(const iRecentUrl *d) {
23 iRecentUrl *copy = new_RecentUrl();
24 set_String(&copy->url, &d->url);
25 copy->scrollY = d->scrollY;
26 copy->cachedResponse = d->cachedResponse ? copy_GmResponse(d->cachedResponse) : NULL;
27 return copy;
28}
29
20/*----------------------------------------------------------------------------------------------*/ 30/*----------------------------------------------------------------------------------------------*/
21 31
22struct Impl_History { 32struct Impl_History {
@@ -36,6 +46,15 @@ void deinit_History(iHistory *d) {
36 deinit_Array(&d->recent); 46 deinit_Array(&d->recent);
37} 47}
38 48
49iHistory *copy_History(const iHistory *d) {
50 iHistory *copy = new_History();
51 iConstForEach(Array, i, &d->recent) {
52 pushBack_Array(&copy->recent, copy_RecentUrl(i.value));
53 }
54 copy->recentPos = d->recentPos;
55 return copy;
56}
57
39void save_History(const iHistory *d, const char *dirPath) { 58void save_History(const iHistory *d, const char *dirPath) {
40 iString *line = new_String(); 59 iString *line = new_String();
41 iFile *f = newCStr_File(concatPath_CStr(dirPath, "recent.txt")); 60 iFile *f = newCStr_File(concatPath_CStr(dirPath, "recent.txt"));
diff --git a/src/history.h b/src/history.h
index bb7f5c88..9deae8ea 100644
--- a/src/history.h
+++ b/src/history.h
@@ -20,6 +20,8 @@ struct Impl_RecentUrl {
20iDeclareType(History) 20iDeclareType(History)
21iDeclareTypeConstruction(History) 21iDeclareTypeConstruction(History)
22 22
23iHistory * copy_History (const iHistory *);
24
23void clear_History (iHistory *); 25void clear_History (iHistory *);
24void load_History (iHistory *, const char *dirPath); 26void load_History (iHistory *, const char *dirPath);
25void add_History (iHistory *, const iString *url); 27void add_History (iHistory *, const iString *url);
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) {
280} 280}
281 281
282static void updateWindowTitle_DocumentWidget_(const iDocumentWidget *d) { 282static void updateWindowTitle_DocumentWidget_(const iDocumentWidget *d) {
283 iLabelWidget *tabButton = tabPageButton_Widget(findWidget_App("doctabs"), d);
284 if (!tabButton) {
285 /* Not part of the UI at the moment. */
286 return;
287 }
283 iStringArray *title = iClob(new_StringArray()); 288 iStringArray *title = iClob(new_StringArray());
284 if (!isEmpty_String(title_GmDocument(d->doc))) { 289 if (!isEmpty_String(title_GmDocument(d->doc))) {
285 pushBack_StringArray(title, title_GmDocument(d->doc)); 290 pushBack_StringArray(title, title_GmDocument(d->doc));
@@ -298,7 +303,6 @@ static void updateWindowTitle_DocumentWidget_(const iDocumentWidget *d) {
298 pushBackCStr_StringArray(title, "Lagrange"); 303 pushBackCStr_StringArray(title, "Lagrange");
299 } 304 }
300 /* Take away parts if it doesn't fit. */ 305 /* Take away parts if it doesn't fit. */
301 iLabelWidget *tabButton = tabPageButton_Widget(findWidget_App("doctabs"), d);
302 const int avail = bounds_Widget(as_Widget(tabButton)).size.x - 3 * gap_UI; 306 const int avail = bounds_Widget(as_Widget(tabButton)).size.x - 3 * gap_UI;
303 iBool setWindow = (document_App() == d); 307 iBool setWindow = (document_App() == d);
304 for (;;) { 308 for (;;) {
@@ -455,9 +459,11 @@ static void fetch_DocumentWidget_(iDocumentWidget *d) {
455static void updateTrust_DocumentWidget_(iDocumentWidget *d, const iGmResponse *response) { 459static void updateTrust_DocumentWidget_(iDocumentWidget *d, const iGmResponse *response) {
456#define openLock_CStr "\U0001f513" 460#define openLock_CStr "\U0001f513"
457#define closedLock_CStr "\U0001f512" 461#define closedLock_CStr "\U0001f512"
458 d->certFlags = response->certFlags; 462 if (response) {
459 d->certExpiry = response->certValidUntil; 463 d->certFlags = response->certFlags;
460 set_String(d->certSubject, &response->certSubject); 464 d->certExpiry = response->certValidUntil;
465 set_String(d->certSubject, &response->certSubject);
466 }
461 iLabelWidget *lock = findWidget_App("navbar.lock"); 467 iLabelWidget *lock = findWidget_App("navbar.lock");
462 if (~d->certFlags & available_GmCertFlag) { 468 if (~d->certFlags & available_GmCertFlag) {
463 setFlags_Widget(as_Widget(lock), disabled_WidgetFlag, iTrue); 469 setFlags_Widget(as_Widget(lock), disabled_WidgetFlag, iTrue);
@@ -516,6 +522,16 @@ void setUrlFromCache_DocumentWidget(iDocumentWidget *d, const iString *url, iBoo
516 } 522 }
517} 523}
518 524
525iDocumentWidget *duplicate_DocumentWidget(iDocumentWidget *orig) {
526 iDocumentWidget *d = new_DocumentWidget();
527 delete_History(d->history);
528 d->textSizePercent = orig->textSizePercent;
529 d->initialScrollY = orig->scrollY;
530 d->history = copy_History(orig->history);
531 setUrlFromCache_DocumentWidget(d, orig->url, iTrue);
532 return d;
533}
534
519void setUrl_DocumentWidget(iDocumentWidget *d, const iString *url) { 535void setUrl_DocumentWidget(iDocumentWidget *d, const iString *url) {
520 setUrlFromCache_DocumentWidget(d, url, iFalse); 536 setUrlFromCache_DocumentWidget(d, url, iFalse);
521} 537}
@@ -754,11 +770,14 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
754 if (cmp_String(id_Widget(w), suffixPtr_Command(cmd, "id")) == 0) { 770 if (cmp_String(id_Widget(w), suffixPtr_Command(cmd, "id")) == 0) {
755 /* Set palette for our document. */ 771 /* Set palette for our document. */
756 updateTheme_DocumentWidget_(d); 772 updateTheme_DocumentWidget_(d);
773 updateTrust_DocumentWidget_(d, NULL);
774 setWidth_GmDocument(d->doc, documentWidth_DocumentWidget_(d));
775 updateVisible_DocumentWidget_(d);
757 } 776 }
758 updateWindowTitle_DocumentWidget_(d); 777 updateWindowTitle_DocumentWidget_(d);
759 return iFalse; 778 return iFalse;
760 } 779 }
761 else if (equal_Command(cmd, "server.showcert")) { 780 else if (equal_Command(cmd, "server.showcert") && d == document_App()) {
762 const char *unchecked = red_ColorEscape "\u2610"; 781 const char *unchecked = red_ColorEscape "\u2610";
763 const char *checked = green_ColorEscape "\u2611"; 782 const char *checked = green_ColorEscape "\u2611";
764 makeMessage_Widget( 783 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)
7iDeclareWidgetClass(DocumentWidget) 7iDeclareWidgetClass(DocumentWidget)
8iDeclareObjectConstruction(DocumentWidget) 8iDeclareObjectConstruction(DocumentWidget)
9 9
10iHistory * history_DocumentWidget (iDocumentWidget *); 10iDocumentWidget *duplicate_DocumentWidget (iDocumentWidget *);
11iHistory * history_DocumentWidget (iDocumentWidget *);
12
13const iString * url_DocumentWidget (const iDocumentWidget *);
14iBool isRequestOngoing_DocumentWidget (const iDocumentWidget *);
11 15
12void setUrl_DocumentWidget (iDocumentWidget *, const iString *url); 16void setUrl_DocumentWidget (iDocumentWidget *, const iString *url);
13void setUrlFromCache_DocumentWidget (iDocumentWidget *d, const iString *url, iBool isFromCache); 17void setUrlFromCache_DocumentWidget (iDocumentWidget *d, const iString *url, iBool isFromCache);
14void setInitialScroll_DocumentWidget (iDocumentWidget *, int scrollY); /* set after content received */ 18void setInitialScroll_DocumentWidget (iDocumentWidget *, int scrollY); /* set after content received */
15
16const iString * url_DocumentWidget (const iDocumentWidget *);
17iBool 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) {
195 195
196void openMenu_Widget(iWidget *d, iInt2 coord) { 196void openMenu_Widget(iWidget *d, iInt2 coord) {
197 /* Menu closes when commands are emitted, so handle any pending ones beforehand. */ 197 /* Menu closes when commands are emitted, so handle any pending ones beforehand. */
198 postCommand_App("cancel"); /* dismiss any other menus */
199 processEvents_App(postedEventsOnly_AppEventMode);
198 setFlags_Widget(d, hidden_WidgetFlag, iFalse); 200 setFlags_Widget(d, hidden_WidgetFlag, iFalse);
199 arrange_Widget(d); 201 arrange_Widget(d);
200 d->rect.pos = coord; 202 d->rect.pos = coord;
@@ -318,7 +320,7 @@ static void addTabPage_Widget_(iWidget *tabs, enum iWidgetAddPos addPos, iWidget
318 iClob(new_LabelWidget(label, key, kmods, format_CStr("tabs.switch page:%p", page))), 320 iClob(new_LabelWidget(label, key, kmods, format_CStr("tabs.switch page:%p", page))),
319 addPos); 321 addPos);
320 setFlags_Widget(button, selected_WidgetFlag, isSel); 322 setFlags_Widget(button, selected_WidgetFlag, isSel);
321 setFlags_Widget(button, expand_WidgetFlag, iTrue); 323 setFlags_Widget(button, commandOnClick_WidgetFlag | expand_WidgetFlag, iTrue);
322 addChildPos_Widget(pages, page, addPos); 324 addChildPos_Widget(pages, page, addPos);
323 setFlags_Widget(page, hidden_WidgetFlag | disabled_WidgetFlag, !isSel); 325 setFlags_Widget(page, hidden_WidgetFlag | disabled_WidgetFlag, !isSel);
324} 326}
@@ -388,6 +390,10 @@ iLabelWidget *tabPageButton_Widget(iWidget *tabs, const iAnyObject *page) {
388 return tabButtonForPage_Widget_(tabs, page); 390 return tabButtonForPage_Widget_(tabs, page);
389} 391}
390 392
393iBool isTabButton_Widget(const iWidget *d) {
394 return d->parent && cmp_String(id_Widget(d->parent), "tabs.buttons") == 0;
395}
396
391void setTabPageLabel_Widget(iWidget *tabs, const iAnyObject *page, const iString *label) { 397void setTabPageLabel_Widget(iWidget *tabs, const iAnyObject *page, const iString *label) {
392 iLabelWidget *button = tabButtonForPage_Widget_(tabs, page); 398 iLabelWidget *button = tabButtonForPage_Widget_(tabs, page);
393 setText_LabelWidget(button, label); 399 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
94 94
95/*-----------------------------------------------------------------------------------------------*/ 95/*-----------------------------------------------------------------------------------------------*/
96 96
97iWidget * makeTabs_Widget (iWidget *parent); 97iWidget * makeTabs_Widget (iWidget *parent);
98void appendTabPage_Widget (iWidget *tabs, iWidget *page, const char *label, int key, int kmods); 98void appendTabPage_Widget (iWidget *tabs, iWidget *page, const char *label, int key, int kmods);
99void prependTabPage_Widget (iWidget *tabs, iWidget *page, const char *label, int key, int kmods); 99void prependTabPage_Widget (iWidget *tabs, iWidget *page, const char *label, int key, int kmods);
100iWidget * tabPage_Widget (iWidget *tabs, size_t index); 100iWidget * removeTabPage_Widget (iWidget *tabs, size_t index); /* returns the page */
101iLabelWidget *tabPageButton_Widget (iWidget *tabs, const iAnyObject *page); 101void showTabPage_Widget (iWidget *tabs, const iWidget *page);
102iWidget * removeTabPage_Widget (iWidget *tabs, size_t index); /* returns the page */ 102void setTabPageLabel_Widget (iWidget *tabs, const iAnyObject *page, const iString *label);
103void showTabPage_Widget (iWidget *tabs, const iWidget *page); 103iWidget * tabPage_Widget (iWidget *tabs, size_t index);
104void setTabPageLabel_Widget (iWidget *tabs, const iAnyObject *page, const iString *label); 104iLabelWidget * tabPageButton_Widget (iWidget *tabs, const iAnyObject *page);
105size_t tabPageIndex_Widget (const iWidget *tabs, const iAnyObject *page); 105iBool isTabButton_Widget (const iWidget *);
106const iWidget *currentTabPage_Widget(const iWidget *tabs); 106size_t tabPageIndex_Widget (const iWidget *tabs, const iAnyObject *page);
107size_t tabCount_Widget (const iWidget *tabs); 107const iWidget * currentTabPage_Widget (const iWidget *tabs);
108size_t tabCount_Widget (const iWidget *tabs);
108 109
109/*-----------------------------------------------------------------------------------------------*/ 110/*-----------------------------------------------------------------------------------------------*/
110 111
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) {
419 return iTrue; 419 return iTrue;
420 } 420 }
421 } 421 }
422 else if (d->flags & commandOnClick_WidgetFlag && (ev->type == SDL_MOUSEBUTTONDOWN ||
423 ev->type == SDL_MOUSEBUTTONUP) &&
424 contains_Widget(d, init_I2(ev->button.x, ev->button.y))) {
425 postCommand_Widget(d,
426 "mouse.clicked arg:%d button:%d coord:%d %d",
427 ev->type == SDL_MOUSEBUTTONDOWN ? 1 : 0,
428 ev->button.button,
429 ev->button.x,
430 ev->button.y);
431 return iTrue;
432 }
422 switch (ev->type) { 433 switch (ev->type) {
423 case SDL_USEREVENT: { 434 case SDL_USEREVENT: {
424 if (ev->user.code == command_UserEventCode && d->commandHandler && 435 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 {
30 alignLeft_WidgetFlag = iBit(6), 30 alignLeft_WidgetFlag = iBit(6),
31 alignRight_WidgetFlag = iBit(7), 31 alignRight_WidgetFlag = iBit(7),
32 frameless_WidgetFlag = iBit(8), 32 frameless_WidgetFlag = iBit(8),
33 commandOnClick_WidgetFlag = iBit(9),
33 drawKey_WidgetFlag = iBit(10), 34 drawKey_WidgetFlag = iBit(10),
34 focusable_WidgetFlag = iBit(11), 35 focusable_WidgetFlag = iBit(11),
35 tight_WidgetFlag = iBit(31), /* smaller padding */ 36 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) {
140 updateTextCStr_LabelWidget(findChild_Widget(navBar, "reload"), 140 updateTextCStr_LabelWidget(findChild_Widget(navBar, "reload"),
141 isRequestOngoing_DocumentWidget(doc) ? stopCStr_ : reloadCStr_); 141 isRequestOngoing_DocumentWidget(doc) ? stopCStr_ : reloadCStr_);
142 } 142 }
143 else if (equal_Command(cmd, "mouse.clicked")) {
144 iWidget *widget = pointer_Command(cmd);
145 iWidget *menu = findWidget_App("doctabs.menu");
146 if (isTabButton_Widget(widget)) {
147 iWidget *tabs = findWidget_App("doctabs");
148 showTabPage_Widget(tabs,
149 tabPage_Widget(tabs, childIndex_Widget(widget->parent, widget)));
150 openMenu_Widget(menu, coord_Command(cmd));
151 }
152 }
143 else if (equal_Command(cmd, "navigate.reload")) { 153 else if (equal_Command(cmd, "navigate.reload")) {
144 iDocumentWidget *doc = document_Command(cmd); 154 iDocumentWidget *doc = document_Command(cmd);
145 if (isRequestOngoing_DocumentWidget(doc)) { 155 if (isRequestOngoing_DocumentWidget(doc)) {
@@ -265,156 +275,17 @@ static void setupUserInterface_Window(iWindow *d) {
265 addChild_Widget(searchBar, iClob(newIcon_LabelWidget(" \u2b9d ", 'g', KMOD_PRIMARY | KMOD_SHIFT, "find.prev"))); 275 addChild_Widget(searchBar, iClob(newIcon_LabelWidget(" \u2b9d ", 'g', KMOD_PRIMARY | KMOD_SHIFT, "find.prev")));
266 addChild_Widget(searchBar, iClob(newIcon_LabelWidget("\u2a2f", SDLK_ESCAPE, 0, "find.close"))); 276 addChild_Widget(searchBar, iClob(newIcon_LabelWidget("\u2a2f", SDLK_ESCAPE, 0, "find.close")));
267 } 277 }
268 278 iWidget *tabsMenu = makeMenu_Widget(d->root,
269#if 0 279 (iMenuItem[]){
270 iWidget *mainDiv = makeHDiv_Widget(); 280 { "Close Tab", 0, 0, "tabs.close" },
271 setId_Widget(mainDiv, "maindiv"); 281 { "Duplicate Tab", 0, 0, "tabs.new duplicate:1" },
272 addChild_Widget(d->root, iClob(mainDiv)); 282 { "---", 0, 0, NULL },
273 283 { "Close Other Tabs", 0, 0, "tabs.close toleft:1 toright:1" },
274 iWidget *sidebar = makeVDiv_Widget(); 284 { "Close Tabs To Left", 0, 0, "tabs.close toleft:1" },
275 setFlags_Widget(sidebar, arrangeWidth_WidgetFlag, iTrue); 285 { "Close Tabs To Right", 0, 0, "tabs.close toright:1" },
276 setId_Widget(sidebar, "sidebar"); 286 },
277 addChild_Widget(mainDiv, iClob(sidebar)); 287 6);
278 288 setId_Widget(tabsMenu, "doctabs.menu");
279 /* Menus. */ {
280#if defined (iPlatformApple) && !defined (iPlatformIOS)
281 /* Use the native menus. */
282 insertMenuItems_MacOS("File", fileMenuItems, iElemCount(fileMenuItems));
283 insertMenuItems_MacOS("Edit", editMenuItems, iElemCount(editMenuItems));
284 insertMenuItems_MacOS("View", viewMenuItems, iElemCount(viewMenuItems));
285#else
286 iWidget *menubar = new_Widget();
287 setBackgroundColor_Widget(menubar, gray25_ColorId);
288 setFlags_Widget(menubar, arrangeHorizontal_WidgetFlag | arrangeHeight_WidgetFlag, iTrue);
289 addChild_Widget(menubar, iClob(makeMenuButton_LabelWidget("File", fileMenuItems, iElemCount(fileMenuItems))));
290 addChild_Widget(menubar, iClob(makeMenuButton_LabelWidget("Edit", editMenuItems, iElemCount(editMenuItems))));
291 addChild_Widget(menubar, iClob(makeMenuButton_LabelWidget("View", viewMenuItems, iElemCount(viewMenuItems))));
292 addChild_Widget(sidebar, iClob(menubar));
293#endif
294 }
295 /* Tracker info. */ {
296 iWidget *trackerInfo = addChild_Widget(sidebar, iClob(new_Widget()));
297 setId_Widget(trackerInfo, "trackerinfo");
298 trackerInfo->rect.size.y = lineHeight_Text(default_FontId) + 2 * gap_UI;
299 setFlags_Widget(trackerInfo, arrangeHorizontal_WidgetFlag | resizeChildren_WidgetFlag, iTrue);
300 setId_Widget(
301 addChild_Widget(trackerInfo, iClob(new_LabelWidget("", 'p', KMOD_PRIMARY, "pattern.goto arg:-1"))),
302 "trackerinfo.current");
303 iLabelWidget *dims = new_LabelWidget("", 'r', KMOD_PRIMARY | KMOD_ALT, "pattern.resize");
304 setId_Widget(addChild_Widget(trackerInfo, iClob(dims)), "trackerinfo.dims");
305 }
306
307 iLibraryWidget *lib = new_LibraryWidget();
308 setId_Widget(as_Widget(lib), "library");
309 addChildFlags_Widget(sidebar, iClob(lib), expand_WidgetFlag);
310
311 iPlaybackWidget *play = new_PlaybackWidget();
312 setId_Widget(as_Widget(play), "playback");
313 addChild_Widget(sidebar, iClob(play));
314
315 iWidget *mainTabs = makeTabs_Widget(mainDiv);
316 setId_Widget(mainTabs, "maintabs");
317 setFlags_Widget(mainTabs, expand_WidgetFlag, iTrue);
318
319 /* Optional sidebar on the right. */
320 iWidget *sidebar2 = new_Widget();
321 setId_Widget(addChild_Widget(mainDiv, iClob(sidebar2)), "sidebar2");
322 setFlags_Widget(
323 sidebar2, fixedWidth_WidgetFlag | frameless_WidgetFlag | resizeChildren_WidgetFlag, iTrue);
324
325 /* Pattern sequence. */ {
326 iSequenceWidget *seq = new_SequenceWidget();
327 appendTabPage_Widget(mainTabs, iClob(seq), "SEQUENCE", 0, 0);
328 }
329 /* Tracker. */ {
330 iTrackerWidget *tracker = new_TrackerWidget();
331 appendTabPage_Widget(mainTabs, as_Widget(tracker), "PATTERN", 0, 0);
332 }
333 /* Voice editor. */ {
334 iWidget *voice = as_Widget(new_VoiceWidget());
335 setId_Widget(voice, "voicelayers");
336 appendTabPage_Widget(mainTabs, iClob(voice), "VOICE", '3', KMOD_PRIMARY);
337 }
338 /* Song information. */ {
339 iWidget *songPage = new_Widget();
340 setId_Widget(songPage, "songinfo");
341 setFlags_Widget(songPage, arrangeHorizontal_WidgetFlag, iTrue);
342 iWidget *headings =
343 addChildFlags_Widget(songPage,
344 iClob(new_Widget()),
345 resizeToParentHeight_WidgetFlag | resizeChildren_WidgetFlag |
346 arrangeVertical_WidgetFlag | arrangeWidth_WidgetFlag);
347 iWidget *values = addChildFlags_Widget(
348 songPage, iClob(new_Widget()), arrangeVertical_WidgetFlag | arrangeSize_WidgetFlag);
349
350 setId_Widget(addChild_Widget(headings, iClob(makePadding_Widget(2 * gap_UI))), "headings.padding");
351 setId_Widget(addChild_Widget(values, iClob(makePadding_Widget(2 * gap_UI))), "values.padding");
352
353 addChild_Widget(headings, iClob(makeHeading_Widget(cyan_ColorEscape "SONG PROPERTIES")));
354 addChild_Widget(values, iClob(makeHeading_Widget("")));
355
356 const int fieldWidth = advance_Text(monospace_FontId, "A").x * 40;
357 iWidget *field;
358
359 addChild_Widget(headings, iClob(makeHeading_Widget("Title:")));
360 setId_Widget(field = addChild_Widget(values, iClob(new_InputWidget(0))), "info.title");
361 field->rect.size.x = fieldWidth;
362
363 addChild_Widget(headings, iClob(makeHeading_Widget("Author:")));
364 setId_Widget(field = addChild_Widget(values, iClob(new_InputWidget(0))), "info.author");
365 field->rect.size.x = fieldWidth;
366
367 addChild_Widget(headings, iClob(makeHeading_Widget("Tempo:")));
368 setId_Widget(addChild_Widget(values, iClob(new_InputWidget(3))), "info.tempo");
369
370 addChild_Widget(headings, iClob(makeHeading_Widget("Events per Beat:")));
371 setId_Widget(addChild_Widget(values, iClob(new_InputWidget(2))), "info.eventsperbeat");
372
373 addChild_Widget(headings, iClob(makeHeading_Widget("Num of Tracks:")));
374 setId_Widget(addChild_Widget(values, iClob(new_InputWidget(2))), "info.numtracks");
375
376 addChild_Widget(headings, iClob(makePadding_Widget(2 * gap_UI)));
377 addChild_Widget(values, iClob(makePadding_Widget(2 * gap_UI)));
378
379 addChild_Widget(headings, iClob(makeHeading_Widget(cyan_ColorEscape "SONG METADATA")));
380 addChild_Widget(values, iClob(makeHeading_Widget("")));
381
382 addChild_Widget(headings, iClob(makeHeading_Widget("Duration:")));
383 setId_Widget(addChildFlags_Widget(values, iClob(newEmpty_LabelWidget()),
384 alignLeft_WidgetFlag | frameless_WidgetFlag),
385 "info.duration");
386 addChild_Widget(headings, iClob(makeHeading_Widget("Statistics:\n\n ")));
387 setId_Widget(addChildFlags_Widget(values,
388 iClob(newEmpty_LabelWidget()),
389 alignLeft_WidgetFlag | frameless_WidgetFlag),
390 "info.statistics");
391 addChild_Widget(headings, iClob(makeHeading_Widget("Created on:")));
392 setId_Widget(addChildFlags_Widget(values,
393 iClob(newEmpty_LabelWidget()),
394 alignLeft_WidgetFlag | frameless_WidgetFlag),
395 "info.created");
396
397 addChild_Widget(headings, iClob(makeHeading_Widget("Last Modified on:")));
398 setId_Widget(addChildFlags_Widget(values,
399 iClob(newEmpty_LabelWidget()),
400 alignLeft_WidgetFlag | frameless_WidgetFlag),
401 "info.lastmodified");
402 /* App info in the bottom. */ {
403 addChildFlags_Widget(headings, iClob(new_Widget()), expand_WidgetFlag);
404 addChildFlags_Widget(
405 headings,
406 iClob(new_LabelWidget(gray50_ColorEscape "Version " BWH_APP_VERSION, 0, 0, NULL)),
407 frameless_WidgetFlag | alignLeft_WidgetFlag);
408 }
409 appendTabPage_Widget(mainTabs, iClob(songPage), "INFO", '4', KMOD_PRIMARY);
410 }
411 /* Application status. */ {
412 iWidget *status = addChildFlags_Widget(d->root, iClob(newEmpty_LabelWidget()), 0);
413 setFont_LabelWidget((iLabelWidget *) status, monospace_FontId);
414 setFlags_Widget(status, frameless_WidgetFlag | alignRight_WidgetFlag, iTrue);
415 setId_Widget(status, "status");
416 }
417#endif
418 /* Glboal keyboard shortcuts. */ { 289 /* Glboal keyboard shortcuts. */ {
419 addAction_Widget(d->root, SDLK_LEFTBRACKET, KMOD_SHIFT | KMOD_PRIMARY, "tabs.prev"); 290 addAction_Widget(d->root, SDLK_LEFTBRACKET, KMOD_SHIFT | KMOD_PRIMARY, "tabs.prev");
420 addAction_Widget(d->root, SDLK_RIGHTBRACKET, KMOD_SHIFT | KMOD_PRIMARY, "tabs.next"); 291 addAction_Widget(d->root, SDLK_RIGHTBRACKET, KMOD_SHIFT | KMOD_PRIMARY, "tabs.next");