/* Create a standard panel button. * Note that the app owns these handles, so an app may delete one or more buttons. * This means that we _must_ only refer to the buttons by their handle unless of * course we're in a callback triggered by that button. */ g_error panel_std_button(handle *h, struct widget *self, int thobj, int thobj_on, int thobj_hilight, int exev, int (*callback)(int event, struct widget *from, s32 param, int owner, const u8 *data)) { struct widget *w, *bar; g_error e; e = rdhandle((void **) &bar, PG_TYPE_WIDGET, self->owner, DATA->hbar); errorcheck; w = NULL; e = widget_derive(&w,h,PG_WIDGET_BUTTON,bar,DATA->hbar,PG_DERIVE_INSIDE,self->owner); errorcheck; w->callback = callback; w->callback_owner = self; widget_set(w, PG_WP_THOBJ_BUTTON, thobj); widget_set(w, PG_WP_THOBJ_BUTTON_ON, thobj_on); widget_set(w, PG_WP_THOBJ_BUTTON_HILIGHT, thobj_hilight); widget_set(w, PG_WP_THOBJ_BUTTON_ON_NOHILIGHT, thobj_on); widget_set(w, PG_WP_EXTDEVENTS, exev); return success; }
g_error panel_install(struct widget *self) { struct widget *bar, *title; g_error e; WIDGET_ALLOC_DATA(paneldata); /* This split determines the size of the main panel area */ e = newdiv(&self->in,self); errorcheck; self->in->flags &= ~(DIVNODE_SIZE_AUTOSPLIT | DIVNODE_SIZE_RECURSIVE); self->in->flags |= PG_S_TOP; /* An optional border inside that main panel area */ e = newdiv(&self->in->div,self); errorcheck; self->in->div->flags &= ~(DIVNODE_SIZE_AUTOSPLIT | DIVNODE_SIZE_RECURSIVE); self->in->div->flags |= DIVNODE_SPLIT_BORDER; self->in->div->build = &build_panel_border; /* Create the panelbar widget */ e = widget_create(&bar,&DATA->hbar,PG_WIDGET_PANELBAR, self->dt,self->container,self->owner); errorcheck; e = widget_attach(bar,self->dt,&self->in->div->div,0); errorcheck; e = widget_set(bar,PG_WP_BIND,self->h); errorcheck; /* This draws the panel background */ e = newdiv(bar->out,self); errorcheck; DATA->bg = *bar->out; DATA->bg->flags |= DIVNODE_SPLIT_BORDER; DATA->bg->flags &= ~DIVNODE_SIZE_AUTOSPLIT; DATA->bg->build = &build_bgfill_only; DATA->bg->state = PGTH_O_PANEL; /* Set up us the container! */ self->out = &self->in->next; self->sub = &DATA->bg->div; /* Firstly, create a label widget in the panelbar to present the title */ title = NULL; e = widget_derive(&title,&DATA->hlabel,PG_WIDGET_LABEL,bar,DATA->hbar, PG_DERIVE_INSIDE,self->owner); errorcheck; widget_set(title,PG_WP_SIDE,PG_S_ALL); widget_set(title,PG_WP_THOBJ,PGTH_O_PANELBAR); /* Nextly, create the standard buttons for a panel app */ e = panel_std_button(&DATA->hzoom, self, PGTH_O_ZOOMBTN, PGTH_O_ZOOMBTN_ON, PGTH_O_ZOOMBTN_HILIGHT, PG_EXEV_TOGGLE, &panel_zoom_callback); errorcheck; e = panel_std_button(&DATA->hrotate, self, PGTH_O_ROTATEBTN, PGTH_O_ROTATEBTN_ON, PGTH_O_ROTATEBTN_HILIGHT, 0, &panel_rotate_callback); errorcheck; e = panel_std_button(&DATA->hclose, self, PGTH_O_CLOSEBTN, PGTH_O_CLOSEBTN_ON, PGTH_O_CLOSEBTN_HILIGHT, 0, &panel_close_callback); errorcheck; /* Make sure we default to our minimum rolled-up size */ widget_set(self, PG_WP_SIZE, 0); return success; }
/* This is called whenever the widget is attached, after the attaching * process is complete. We use this as a hook for managing the tab and tab_bar. */ g_error tabpage_post_attach(struct widget *self, struct widget *parent, int rship) { struct widget *tab, *tab_bar, *parent_tab; g_error e; handle existing_bar = 0; /* Dereference handles */ e = rdhandle((void**)&tab, PG_TYPE_WIDGET, self->owner, DATA->htab); errorcheck; e = rdhandle((void**)&tab_bar, PG_TYPE_WIDGET, self->owner, DATA->htab_bar); errorcheck; /* Detach our tab. It will be reattached later if necessary */ e = widget_derive(&tab, &DATA->htab, tab->type, NULL, 0, 0, self->owner); errorcheck; /* If we already have a tab bar but it's empty, delete it */ if (DATA->htab_bar && !widget_traverse(tab_bar, PG_TRAVERSE_CHILDREN, 0)) { handle_free(self->owner, DATA->htab_bar); DATA->htab_bar = 0; } /* Are we being attached rather than detached? */ if (parent) { /* If we're attaching before or after another tab page, share its tab bar */ if (parent->type==PG_WIDGET_TABPAGE && (rship==PG_DERIVE_BEFORE || rship==PG_DERIVE_AFTER)) { struct widget *self = parent; existing_bar = DATA->htab_bar; } DATA->htab_bar = existing_bar; /* Otherwise, create a new tab bar */ if (!DATA->htab_bar) { tab_bar = NULL; e = widget_derive(&tab_bar, &DATA->htab_bar, PG_WIDGET_TOOLBAR, self, self->h, PG_DERIVE_BEFORE, self->owner); errorcheck; e = widget_set(tab_bar, PG_WP_THOBJ, PGTH_O_TAB_BAR); errorcheck; tab_bar->auto_orientation = PG_AUTO_SIDE; } /* If we're attaching on an existing bar, attach the tab in the same * relative order as the tab pages themselves. */ parent_tab = NULL; rdhandle((void**)&parent_tab, PG_TYPE_WIDGET, self->owner, widget_get(parent, PG_WP_TAB)); if (existing_bar && parent_tab) { e = widget_derive(&tab, &DATA->htab, tab->type, parent_tab, parent_tab->h, rship, self->owner); errorcheck; } /* Otherwise just put it in our tab bar directly */ else { e = widget_derive(&tab, &DATA->htab, tab->type, tab_bar, tab_bar->h, PG_DERIVE_INSIDE, self->owner); errorcheck; } /* If we were here first, make ourselves active */ if (!existing_bar) { e = widget_set(self, PG_WP_ON, 1); errorcheck; } } return success; }