Beispiel #1
0
g_error widget_derive(struct widget **w, handle *h,
		      int type,struct widget *parent,
		      handle hparent,int rship,int owner) {

  g_error e;

  DBG("type %d, rship %d, parent %p, owner %d\n",type,rship,parent,owner);

  /* Allow using this to detach widgets too. Makes sense, since this is called
   * by the attachwidget request handler.
   */
  if (!parent)
    return widget_attach(*w, NULL, NULL, 0);
  
  switch (rship) {

  case PG_DERIVE_INSIDE:
     if (*w == NULL ) {
        e = widget_create(w,h, type, parent->dt, hparent, owner);
        errorcheck;
     }
     e = widget_attach(*w, parent->dt,parent->sub,hparent);
     break;

  case PG_DERIVE_AFTER:
     if ( *w == NULL ) {
        e = widget_create(w,h, type, parent->dt, parent->container, owner);
        errorcheck;
     }
     e = widget_attach(*w,parent->dt,parent->out,parent->container);
     break;

  case PG_DERIVE_BEFORE:
  case PG_DERIVE_BEFORE_OLD:
     if ( *w == NULL ) {
        e = widget_create(w,h, type, parent->dt, parent->container, owner);
        errorcheck;
     }
     e = widget_attach(*w,parent->dt,parent->where,parent->container);
     break;
     
  default:
    return mkerror(PG_ERRT_BADPARAM,22);

  }
  
  /* Error checking code common to all cases */
  if (iserror(e)) {
    widget_remove(*w);
    errorcheck;
  }

  if ((*w)->def->post_attach) {
    e = (*w)->def->post_attach(*w,parent,rship);
    errorcheck;
  }

  return success;
}
Beispiel #2
0
void widget_remove(struct widget *w) {
  struct widget *child;
  struct divnode **old_where;
  DBG("%p, type %d\n",w,w->type);

  /* Get out of the timer list */
  remove_timer(w);

  /* Detach the widget from the widget tree */
  old_where = w->where;
  widget_attach(w,NULL,NULL,0);

  /* Detach all children from this widget */
  while ((child = widget_traverse(w,PG_TRAVERSE_CHILDREN,0)) && child->where) {
    DBG("removing child %p, type %d. where %p\n",child,child->type,child->where);
    widget_attach(child,NULL,NULL,0);
  }

  /* Note that the widget may have it's 'sub' attachment point filled even
   * if it doesn't have any real children, if it was used inside another widget.
   * We need to reattach any child divnodes this widget still has back to its insertion
   * point, so that they are properly deleted when the widget owning this subtree is
   * finished removing its component pieces.
   * Note that we're attaching it to the widget's former "where" attachment point,
   * since by this time it's been detached from the widget tree and w->where
   * should be NULL.
   */
  if (w->out && *w->out && w->sub && *w->sub) {
    /* If this widget has two subtrees, we need to append them into just one
     * before we link this back into the parent's subtree. A messy process, but
     * cleaner than the alternative (voodoo memory management :)
     */

    struct divnode *n;
    n = *w->sub;
    while (n->next) n = n->next;
    n->next = *w->out;
    if (old_where)
      *old_where = *w->sub;
    *w->out = *w->sub = NULL;
  }
  /* If there's only one child, link it directly */
  else if (w->out && *w->out) {
    if (old_where)
      *old_where = *w->out;
    *w->out = NULL;
  }
  else if (w->sub && *w->sub) {
    if (old_where)
      *old_where = *w->sub;
    *w->sub = NULL;
  }

  /* Free the widget's private data and divnodes */
  if (w->def->remove) (*w->def->remove)(w);
  
  /* Free the array of subclass data */
  g_free(w->subclasses);

  /* Free the widget itself */
#ifdef DEBUG_KEYS
  num_widgets--;
#endif
  g_free(w);
}
Beispiel #3
0
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;
}