aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJorge Arellano Cid <jcid@dillo.org>2011-03-09 14:20:19 -0300
committerJorge Arellano Cid <jcid@dillo.org>2011-03-09 14:20:19 -0300
commit91775fc630020de9f8505fa731272763167cb08e (patch)
tree6ab3c99c939ed6f795cf76669ed26d2edcf564b2 /src
parentf8ec6ac86bcc3b9edda3b5edc30d436c3dae839a (diff)
Made a brand new CustTabs class (to allow fine control of tabs).
Diffstat (limited to 'src')
-rw-r--r--src/ui.hh8
-rw-r--r--src/uicmd.cc472
2 files changed, 165 insertions, 315 deletions
diff --git a/src/ui.hh b/src/ui.hh
index b2c69f8e..053e85d9 100644
--- a/src/ui.hh
+++ b/src/ui.hh
@@ -35,7 +35,7 @@ typedef enum {
// Private classes
class CustProgressBox;
-class CustTabGroup;
+class CustTabs;
// Class definition ----------------------------------------------------------
@@ -115,7 +115,7 @@ public:
// UI class definition -------------------------------------------------------
//
class UI : public Fl_Pack {
- CustTabGroup *Tabs;
+ CustTabs *Tabs;
char *TabTooltip;
Fl_Group *TopGroup;
@@ -172,8 +172,8 @@ public:
Fl_Widget *fullscreen_button() { return FullScreen; }
void fullscreen_toggle() { FullScreen->do_callback(); }
- CustTabGroup *tabs() { return Tabs; }
- void tabs(CustTabGroup *tabs) { Tabs = tabs; }
+ CustTabs *tabs() { return Tabs; }
+ void tabs(CustTabs *tabs) { Tabs = tabs; }
int pointerOnLink() { return PointerOnLink; }
void pointerOnLink(int flag) { PointerOnLink = flag; }
diff --git a/src/uicmd.cc b/src/uicmd.cc
index 0c25a4f4..74cfbb7b 100644
--- a/src/uicmd.cc
+++ b/src/uicmd.cc
@@ -16,10 +16,11 @@
#include <stdarg.h>
#include <math.h> /* for rint */
+#include <FL/Fl.H>
#include <FL/Fl_Widget.H>
#include <FL/Fl_Double_Window.H>
-#include <FL/Fl_Tabs.H>
-#include <FL/Fl_Tooltip.H>
+#include <FL/Fl_Wizard.H>
+#include <FL/Fl_Box.H>
#include "paths.hh"
#include "keys.hh"
@@ -57,321 +58,193 @@ static char *save_dir = NULL;
//----------------------------------------------------------------------------
-#if 0
-
-#define BTN_W 25
-#define BTN_H 20
-static int btn_x;
+/*
+ * CustTabs ---------------------------------------------------------------
+ */
/*
- * Adds a tab-close button at the rightmost part
+ * stores the respective UI pointer
*/
-class CustShrinkTabPager : public TabGroupPager {
- bool btn_hl;
- TabGroup *tg;
+class CustTabButton : public Fl_Button {
+ UI *ui_;
public:
- int update_positions(
- TabGroup *g, int numchildren, int &selected,
- int &cumulated_width, int &available_width,
- int *tab_pos, int *tab_width);
- virtual int which(TabGroup* g, int m_x,int m_y);
- virtual TabGroupPager* clone() const;
- virtual const char * mode_name() const {return "Shrink";}
- virtual int id() const {return PAGER_SHRINK;}
- virtual int available_width(TabGroup *g) const;
- virtual bool draw_tabs(TabGroup* g, int selected, int* tab_pos,
- int* tab_width) {
- if (!tg) tg = g;
- if (g->children() > 1) {
- fltk::Rectangle r(btn_x,0,BTN_W,BTN_H);
- setcolor(btn_hl ? 206 : GRAY75);
- fillrect(r);
- if (btn_hl) {
- setcolor(FL_WHITE);
- strokerect(r);
- }
- setcolor(GRAY10);
- //fltk::setfont(fltk::getfont()->bold(), fltk::getsize());
- r.h(r.h()-2);
- drawtext("X", r, ALIGN_CENTER);
- return false;
- } else {
- // WORKAROUND: for http://fltk.org/str.php?L2062
- // By returning true we avoid a call to TabGroup::draw_tab()
- // in TabGroup::draw() in case we don't show the tabs.
- return true;
- }
- }
+ CustTabButton (int x,int y,int w,int h, const char* label = 0) :
+ Fl_Button (x,y,w,h,label) { ui_ = NULL; };
+ void ui(UI *pui) { ui_ = pui; }
+ UI *ui(void) { return ui_; }
+};
- void btn_highlight(bool flag) {
- if (btn_hl != flag) {
- btn_hl = flag;
- if (tg)
- tg->redraw(DAMAGE_VALUE);
- }
+/*
+ * Allows fine control of the tabbed interface
+ */
+class CustTabs : public CustGroup {
+ int tab_w, tab_h, tab_n;
+ Fl_Wizard *Wizard;
+ int tabcolor_inactive, tabcolor_active, curtab_idx;
+public:
+ CustTabs (int ww, int wh, int th, const char *lbl=0) :
+ CustGroup(0,0,ww,th,lbl) {
+ tab_w = 80, tab_h = th, tab_n = 0, curtab_idx = -1;
+ tabcolor_active = FL_DARK_CYAN; tabcolor_inactive = 206;
+ //Fl_Box *w = new Fl_Box(tab_w,0,ww-tab_w,tab_h,"i n v i s i b l e");
+ Fl_Box *w = new Fl_Box(0,0,0,0,"i n v i s i b l e");
+ w->box(FL_NO_BOX);
+ resizable(0);
+ end();
+
+ Wizard = new Fl_Wizard(0,tab_h,ww,wh-tab_h);
+ Wizard->end();
+ add_new_tab(1);
};
- bool btn_highlight() { return btn_hl; };
-
- CustShrinkTabPager() : TabGroupPager() {
- noclip(true);
- btn_hl = false;
- tg = NULL;
- }
+ int handle(int e);
+ UI *add_new_tab(int focus);
+ void remove_tab();
+ Fl_Wizard *wizard(void) { return Wizard; }
+ int get_btn_idx(UI *ui);
+ void switch_tab(CustTabButton *cbtn);
+ void prev_tab(void);
+ void next_tab(void);
};
-int CustShrinkTabPager::available_width(TabGroup *g) const
-{
- _MSG("CustShrinkTabPager::available_width\n");
- int w = MAX (g->w() - this->slope()-1 - BTN_W, 0);
- btn_x = w + 6;
- return w;
-}
-
-int CustShrinkTabPager::which(TabGroup* g, int event_x,int event_y)
-{
- int H = g->tab_height();
- if (!H) return -1;
- if (H < 0) {
- if (event_y > g->h() || event_y < g->h()+H) return -1;
- } else {
- if (event_y > H || event_y < 0) return -1;
- }
- if (event_x < 0) return -1;
- int p[128], w[128];
- int selected = g->tab_positions(p, w);
- int d = (event_y-(H>=0?0:g->h()))*slope()/H;
- for (int i=0; i<g->children(); i++) {
- if (event_x < p[i+1]+(i<selected ? slope() - d : d)) return i;
+int CustTabs::handle(int e)
+{
+ int ret = 0;
+
+ //printf("CustTabs::handle e=%s\n", fl_eventnames[e]);
+ if (e == FL_KEYUP) {
+ int k = Fl::event_key();
+ // We're only interested in some flags
+ unsigned modifier = Fl::event_state() & (FL_SHIFT | FL_CTRL | FL_ALT);
+ if (k == FL_Up || k == FL_Down || k == FL_Tab) {
+ ;
+ } else if (k == FL_Left || k == FL_Right) {
+ if (modifier == FL_SHIFT) {
+ (k == FL_Left) ? prev_tab() : next_tab();
+ ret = 1;
+ }
+ } else if (modifier == FL_CTRL) {
+ if (k == ' ') {
+ //printf("CustTabs::handle FL_CTRL + Space\n");
+ //toggle_cb(NULL, Wizard->value());
+ ret = 1;
+ } else if (k == 't') {
+ add_new_tab(1);
+ } else if (k == 'q') {
+ remove_tab();
+ }
+ }
}
- return -1;
+
+ return (ret) ? ret : CustGroup::handle(e);
}
/*
- * Prevents tabs from going over the close-tab button.
- * Modified from fltk-2.0.x-r6525.
+ * Create a new tab with its own UI
*/
-int CustShrinkTabPager::update_positions(
- TabGroup *g, int numchildren, int &selected,
- int &cumulated_width, int &available_width,
- int *tab_pos, int *tab_width)
+UI *CustTabs::add_new_tab(int focus)
{
- available_width-=BTN_W;
+ char tab_label[64];
- // uh oh, they are too big, we must move them:
- // special case when the selected tab itself is too big, make it fill
- // cumulated_width:
- int i;
+ current(0);
+ UI *new_ui = new UI(0,tab_h,Wizard->w(),Wizard->h());
+ new_ui->tabs(this);
+ Wizard->add(new_ui);
- if (tab_width[selected] >= available_width) {
- tab_width[selected] = available_width;
- for (i = 0; i <= selected; i++)
- tab_pos[i] = 0;
- for (i = selected + 1; i <= numchildren; i++)
- tab_pos[i] = available_width;
- return selected;
- }
+ int ntabs = children();
+ snprintf(tab_label, 64,"ctab%d", ++tab_n);
+ CustTabButton *btn = new CustTabButton((ntabs-1)*tab_w,0,tab_w,tab_h);
+ btn->copy_label(tab_label);
+ btn->clear_visible_focus();
+ btn->box(FL_PLASTIC_ROUND_UP_BOX);
+ btn->color(tabcolor_active);
+ btn->ui(new_ui);
+ add(btn);
+ btn->redraw();
+ //btn->callback(tab_btn_cb, this);
- int w2[128];
+ if (focus)
+ switch_tab(btn);
+ rearrange();
- for (i = 0; i < numchildren; i++)
- w2[i] = tab_width[i];
- i = numchildren - 1;
- int j = 0;
+ return new_ui;
+}
- int minsize = 5;
+void CustTabs::remove_tab()
+{
+ CustTabButton *btn;
+ UI *ui = (UI*)Wizard->value();
- bool right = true;
+ // the invisible box is also a child
+ if (children() == 2)
+ exit(0);
- while (cumulated_width > available_width) {
- int n; // which one to shrink
+ // remove label button
+ int idx = get_btn_idx(ui);
+ btn = (CustTabButton*)child(idx);
+ idx > 1 ? prev_tab() : next_tab();
+ remove(idx);
+ delete btn;
+ rearrange();
+ redraw();
- if (j < selected && (!right || i <= selected)) { // shrink a left one
- n = j++;
- right = true;
- } else if (i > selected) { // shrink a right one
- n = i--;
- right = false;
- } else { // no more space, start making them zero
- minsize = 0;
- i = numchildren - 1;
- j = 0;
- right = true;
- continue;
- }
- cumulated_width -= w2[n] - minsize;
- w2[n] = minsize;
- if (cumulated_width < available_width) {
- w2[n] = available_width - cumulated_width + minsize;
- cumulated_width = available_width;
- break;
- }
- }
- // re-sum the positions:
- cumulated_width = 0;
- for (i = 0; i < numchildren; i++) {
- cumulated_width += w2[i];
- tab_pos[i+1] = cumulated_width;
- }
- return selected;
+ Wizard->remove(ui);
+ delete(ui);
}
-TabGroupPager* CustShrinkTabPager::clone() const {
- return new CustShrinkTabPager(*this);
+int CustTabs::get_btn_idx(UI *ui)
+{
+ for (int i = children()-1; i; --i) {
+ CustTabButton *btn = (CustTabButton*)child(i);
+ if (btn->ui() == ui)
+ return i;
+ }
+ return -1;
}
-#endif /* custom pager */
-//----------------------------------------------------------------------------
-/*
- * For custom handling of keyboard
- */
-class CustTabGroup : public Fl_Tabs {
- Fl_Tooltip *toolTip;
- bool tooltipEnabled;
- bool buttonPushed;
-public:
- CustTabGroup (int x, int y, int ww, int wh, const char *lbl=0) :
- Fl_Tabs(x,y,ww,wh,lbl) {
- Fl_Group::current(0);
- box(FL_NO_BOX);
- // The parameter pager is cloned, so free it.
-// CustShrinkTabPager *cp = new CustShrinkTabPager();
-// this->pager(cp);
-// delete cp;
- toolTip = new Fl_Tooltip;
- tooltipEnabled = false;
- buttonPushed = false;
- };
- ~CustTabGroup() { delete toolTip; }
- int handle(int e) {
- // Don't focus with arrow keys
- _MSG("CustTabGroup::handle %d\n", e);
-// fltk::Rectangle r(btn_x,0,BTN_W,BTN_H);
- if (e == FL_KEYBOARD) {
- int k = Fl::event_key();
- // We're only interested in some flags
- unsigned modifier = Fl::event_state() & (FL_SHIFT | FL_CTRL | FL_ALT);
- if (k == FL_Up || k == FL_Down || k == FL_Tab) {
- return 0;
- } else if (k == FL_Left || k == FL_Right) {
- if (modifier == FL_SHIFT) {
- int i = find(value());
- if (k == FL_Left) {i = i ? i-1 : children()-1;}
- else {i++; if (i >= children()) i = 0;}
- value(child(i));
- return 1;
- }
- // Avoid focus change.
- return 0;
- }
- } else if (e == FL_RELEASE) {
- Fl_Widget *new_focus = which(Fl::event_x(), Fl::event_y());
-
- if (new_focus && new_focus != value()) {
- // Update the window title
- BrowserWindow *bw = a_UIcmd_get_bw_by_widget(new_focus);
- const char *title = a_History_get_title(NAV_TOP_UIDX(bw), 1);
-
- a_UIcmd_set_page_title(bw, title ? title : "");
- }
-// custom pager
-#if 0
- } else if (e == FL_MOVE) {
- CustShrinkTabPager *cstp = (CustShrinkTabPager *) pager();
- if (Fl::event_inside(r) && children() > 1) {
- /* We're inside the button area */
- cstp->btn_highlight(true);
- if (prefs.show_tooltip) {
- /* Prepare the tooltip for pop-up */
- tooltipEnabled = true;
- /* We use parent() if available because we are returning 0.
- * Returning without having TabGroup processing makes the
- * popup event never reach 'this', but it reaches parent() */
- toolTip->enter(parent() ?parent():this, r, "Close current Tab");
- }
- return 0; // Change focus
- } else {
- cstp->btn_highlight(false);
-
- if (prefs.show_tooltip) {
- /* Hide the tooltip or enable it again.*/
- if (tooltipEnabled) {
- tooltipEnabled = false;
- toolTip->exit();
- } else {
- toolTip->enable();
- }
- }
- }
- } else if (e == FL_PUSH && Fl::event_inside(r) &&
- Fl::event_button() == 1 && children() > 1) {
- buttonPushed = true;
- return 1; /* non-zero */
- } else if (e == FL_RELEASE) {
- if (Fl::event_inside(r) && Fl::event_button() == 1 &&
- children() > 1 && buttonPushed) {
- a_UIcmd_close_bw(a_UIcmd_get_bw_by_widget(value()));
- } else {
- CustShrinkTabPager *cstp = (CustShrinkTabPager *) pager();
- cstp->btn_highlight(false);
- }
- buttonPushed = false;
-#endif
- } else if (e == FL_DRAG) {
- /* Ignore this event */
- return 1;
- }
- int ret = Fl_Tabs::handle(e);
+void CustTabs::switch_tab(CustTabButton *cbtn)
+{
+ int idx;
+ CustTabButton *btn;
+ UI *old_ui = (UI*)Wizard->value();
- if (e == FL_PUSH) {
- /* WORKAROUND: FLTK raises the window on unhandled clicks,
- * which we do not want.
- */
- ret = 1;
+ if (cbtn->ui() != old_ui) {
+ // Set old tab label to normal color
+ if ((idx = get_btn_idx(old_ui)) > 0) {
+ btn = (CustTabButton*)child(idx);
+ btn->color(tabcolor_inactive);
+ btn->redraw();
}
- return ret;
+ Wizard->value(cbtn->ui());
+ cbtn->color(tabcolor_active);
+ cbtn->redraw();
}
+}
- void remove (Fl_Widget *w) {
- Fl_Tabs::remove (w);
- /* fixup resizable in case we just removed it */
- if (resizable () == w) {
- if (children () > 0)
- resizable (child (children () - 1));
- else
- resizable (NULL);
- }
+void CustTabs::prev_tab()
+{
+ int idx;
- if (children () < 2) {
- box(FL_NO_BOX);
- hideLabels ();
- }
- }
+ if ((idx = get_btn_idx((UI*)Wizard->value())) > 1)
+ switch_tab( (CustTabButton*)child(idx-1) );
+}
+
+void CustTabs::next_tab()
+{
+ int idx;
+
+ if ((idx = get_btn_idx((UI*)Wizard->value())) > 0 && idx+1 < children())
+ switch_tab( (CustTabButton*)child(idx+1) );
+}
- void add (Fl_Widget *w) {
- Fl_Tabs::add (w);
- if (children () > 1) {
- box(FL_THIN_UP_BOX);
- showLabels ();
- }
- }
- void hideLabels() {
- for (int i = children () - 1; i >= 0; i--)
- child(i)->resize(x(), y(), w(), h());
- }
- void showLabels() {
- for (int i = children () - 1; i >= 0; i--)
- child(i)->resize(x(), y() + 20, w(), h() - 20);
- }
-};
//----------------------------------------------------------------------------
static void win_cb (Fl_Widget *w, void *cb_data) {
int choice = 1;
- CustTabGroup *tabs = (CustTabGroup*) cb_data;
+ CustTabs *tabs = (CustTabs*) cb_data;
if (tabs->children () > 1)
choice = a_Dialog_choice5("Window contains more than one tab.",
@@ -434,26 +307,19 @@ BrowserWindow *a_UIcmd_browser_window_new(int ww, int wh,
win = new Fl_Double_Window(ww, wh);
Fl_Group::current(0);
-//may need a handler for this
-// win->shortcut(0); // Ignore Escape
- CustTabGroup *DilloTabs = new CustTabGroup(0, 0, ww, wh);
+ CustTabs *DilloTabs = new CustTabs(ww, wh, 16);
DilloTabs->selection_color(156);
win->add(DilloTabs);
// Create and set the UI
- UI *new_ui = new UI(0, 0, ww, wh, DEFAULT_TAB_LABEL,
- old_bw ? BW2UI(old_bw) : NULL);
- new_ui->set_status("http://www.dillo.org/");
- new_ui->tabs(DilloTabs);
-
- DilloTabs->add(new_ui);
- DilloTabs->resizable(new_ui);
- DilloTabs->window()->resizable(new_ui);
- DilloTabs->window()->show();
+ UI *new_ui = DilloTabs->add_new_tab(1);
+ win->resizable(new_ui);
+ win->show();
+ //DilloTabs->window()->show();
if (old_bw == NULL && prefs.xpos >= 0 && prefs.ypos >= 0) {
// position the first window according to preferences
- new_ui->window()->position(prefs.xpos, prefs.ypos);
+ DilloTabs->window()->position(prefs.xpos, prefs.ypos);
}
// Now create the Dw render layout and viewport
@@ -492,7 +358,7 @@ BrowserWindow *a_UIcmd_browser_window_new(int ww, int wh,
* Create a new Tab.
* i.e the new UI and its associated BrowserWindow data structure.
*/
-static BrowserWindow *UIcmd_tab_new(const void *vbw)
+static BrowserWindow *UIcmd_tab_new(const void *vbw, int focus)
{
_MSG(" UIcmd_tab_new vbw=%p\n", vbw);
@@ -508,13 +374,7 @@ static BrowserWindow *UIcmd_tab_new(const void *vbw)
0, vbw);
// Create and set the UI
- UI *new_ui = new UI(0, 0, ui->w(), ui->h(), DEFAULT_TAB_LABEL, ui);
- new_ui->tabs(ui->tabs());
-
- new_ui->tabs()->add(new_ui);
- new_ui->tabs()->resizable(new_ui);
- new_ui->tabs()->window()->resizable(new_ui);
- new_ui->tabs()->window()->show();
+ UI *new_ui = ui->tabs()->add_new_tab(focus);
// Now create the Dw render layout and viewport
FltkPlatform *platform = new FltkPlatform ();
@@ -553,14 +413,8 @@ void a_UIcmd_close_bw(void *vbw)
a_Bw_stop_clients(bw, BW_Root + BW_Img + BW_Force);
delete(layout);
if (ui->tabs()) {
- ui->tabs()->remove(ui);
- if (ui->tabs()->value())
- ui->tabs()->value()->take_focus();
- else
- ui->tabs()->window()->hide();
+ ui->tabs()->remove_tab();
}
- delete(ui);
-
a_Bw_free(bw);
}
@@ -663,11 +517,7 @@ void a_UIcmd_open_url_nw(BrowserWindow *bw, const DilloUrl *url)
*/
void a_UIcmd_open_url_nt(void *vbw, const DilloUrl *url, int focus)
{
- BrowserWindow *new_bw = UIcmd_tab_new(vbw);
-
- if (focus)
- BW2UI(new_bw)->tabs()->value(BW2UI(new_bw));
-
+ BrowserWindow *new_bw = UIcmd_tab_new(vbw, focus);
UIcmd_open_url_nbw(new_bw, url);
}
@@ -1234,7 +1084,7 @@ void a_UIcmd_set_page_title(BrowserWindow *bw, const char *label)
const int size = 128;
char title[size];
- if (a_UIcmd_get_bw_by_widget(BW2UI(bw)->tabs()->value()) == bw) {
+ if (a_UIcmd_get_bw_by_widget(BW2UI(bw)->tabs()->wizard()->value()) == bw) {
// This is the focused bw, set window title
if (snprintf(title, size, "Dillo: %s", label) >= size) {
uint_t i = MIN(size - 4, 1 + a_Utf8_end_of_char(title, size - 8));