fl_widget_type.cxx

来自「SRI international 发布的OAA框架软件」· CXX 代码 · 共 1,977 行 · 第 1/5 页

CXX
1,977
字号

// subtypes:

Fl_Menu_Item *Fl_Widget_Type::subtypes() {return 0;}

void subtype_cb(Fl_Choice* i, void* v) {
  if (v == LOAD) {
    Fl_Menu_Item* m = current_widget->subtypes();
    if (!m) {i->deactivate(); return;}
    i->menu(m);
    int j;
    for (j = 0;; j++) {
      if (!m[j].text) {j = 0; break;}
      if (m[j].argument() == current_widget->o->type()) break;
    }
    i->value(j);
    i->activate();
    i->redraw();
  } else {
    int n = int(i->mvalue()->argument());
    Fl_Menu_Item* m = current_widget->subtypes();
    for (Fl_Type *o = Fl_Type::first; o; o = o->next)
      if (o->selected && o->is_widget()) {
	Fl_Widget_Type* q = (Fl_Widget_Type*)o;
	if (q->subtypes()==m) {
	  q->o->type(n);
	  q->redraw();
	}
      }
  }
}

////////////////////////////////////////////////////////////////

void propagate_load(Fl_Group* g, void* v) {
  if (v == LOAD) {
    Fl_Widget*const* a = g->array();
    for (int i=g->children(); i--;) {
      Fl_Widget* o = *a++;
      o->do_callback(o,LOAD);
    }
  }
}

void set_cb(Fl_Button*, void*) {
  haderror = 0;
  Fl_Widget*const* a = the_panel->array();
  for (int i=the_panel->children(); i--;) {
    Fl_Widget* o = *a++;
    if (o->changed()) {
      o->do_callback();
      if (haderror) return;
      o->clear_changed();
    }
  }
}

void ok_cb(Fl_Return_Button* o, void* v) {
  set_cb(o,v);
  if (!haderror) the_panel->hide();
}

void revert_cb(Fl_Button*, void*) {
  // We have to revert all dynamically changing fields:
  // but for now only the first label works...
  if (numselected == 1) current_widget->label(oldlabel);
  propagate_load(the_panel, LOAD);
}

void cancel_cb(Fl_Button* o, void* v) {
  revert_cb(o,v);
  the_panel->hide();
}

void toggle_overlays(Fl_Widget *,void *); // in Fl_Window_Type.C
void overlay_cb(Fl_Button*o,void *v) {
  toggle_overlays(o,v);
}

// update the panel according to current widget set:
static void load_panel() {
  if (!the_panel) return;

  // find all the Fl_Widget subclasses currently selected:
  numselected = 0;
  current_widget = 0;
  if (Fl_Type::current) {
    if (Fl_Type::current->is_widget())
      current_widget=(Fl_Widget_Type*)Fl_Type::current;
    for (Fl_Type *o = Fl_Type::first; o; o = o->next) {
      if (o->is_widget() && o->selected) {
	numselected++;
	if (!current_widget) current_widget = (Fl_Widget_Type*)o;
      }
    }
  }
  if (numselected)
    propagate_load(the_panel, LOAD);
  else
    the_panel->hide();
}

// This is called when user double-clicks an item, open or update the panel:
void Fl_Widget_Type::open() {
  if (!the_panel) the_panel = make_widget_panel();
  load_panel();
  if (numselected) the_panel->show();
}

Fl_Type *Fl_Type::current;

extern void redraw_overlays();
extern void redraw_browser();

// Called when ui changes what objects are selected:
// p is selected object, null for all deletions (we must throw away
// old panel in that case, as the object may no longer exist)
void selection_changed(Fl_Type *p) {
  // store all changes to the current selected objects:
  if (p && the_panel && the_panel->visible()) {
    set_cb(0,0);
    // if there was an error, we try to leave the selected set unchanged:
    if (haderror) {
      Fl_Type *q = 0;
      for (Fl_Type *o = Fl_Type::first; o; o = o->next) {
	o->new_selected = o->selected;
	if (!q && o->selected) q = o;
      }
      if (!p || !p->selected) p = q;
      Fl_Type::current = p;
      redraw_browser();
      return;
    }
  }
  // update the selected flags to new set:
  Fl_Type *q = 0;
  for (Fl_Type *o = Fl_Type::first; o; o = o->next) {
    o->selected = o->new_selected;
    if (!q && o->selected) q = o;
  }
  if (!p || !p->selected) p = q;
  Fl_Type::current = p;
  redraw_overlays();
  // load the panel with the new settings:
  load_panel();
}

////////////////////////////////////////////////////////////////
// Writing the C code:

// test to see if user named a function, or typed in code:
int is_name(const char *c) {
  for (; *c; c++) if (ispunct(*c) && *c!='_' && *c!=':') return 0;
  return 1;
}

// Test to see if name() is an array entry.  If so, and this is the
// highest number, return name[num+1].  Return null if not the highest
// number or a field or function.  Return name() if not an array entry.
const char *array_name(Fl_Widget_Type *o) {
  const char *c = o->name();
  if (!c) return 0;
  const char *d;
  for (d = c; *d != '['; d++) {
    if (!*d) return c;
    if (ispunct(*d) && *d!='_') return 0;
  }
  int num = atoi(d+1);
  int sawthis = 0;
  Fl_Type *t = o->prev;
  Fl_Type *tp = o;
  const char *cn = o->class_name(1);
  for (; t && t->class_name(1) == cn; tp = t, t = t->prev);
  for (t = tp; t && t->class_name(1) == cn; t = t->next) {
    if (t == o) {sawthis=1; continue;}
    const char *e = t->name();
    if (!e) continue;
    if (strncmp(c,e,d-c)) continue;
    int n1 = atoi(e+(d-c)+1);
    if (n1 > num || n1==num && sawthis) return 0;
  }
  static char buffer[128];
  // MRS: we want strncpy() here...
  strncpy(buffer,c,d-c+1);
  snprintf(buffer+(d-c+1),sizeof(buffer) - (d-c+1), "%d]",num+1);
  return buffer;
}

// Test to see if extra code is a declaration:
int isdeclare(const char *c) {
  while (isspace(*c)) c++;
  if (*c == '#') return 1;
  if (!strncmp(c,"extern",6)) return 1;
  if (!strncmp(c,"typedef",7)) return 1;
  if (!strncmp(c,"using",5)) return 1;
  return 0;
}

void Fl_Widget_Type::write_static() {
  const char* t = subclassname(this);
  if (!subclass()) write_declare("#include <FL/%s.H>", t);
  for (int n=0; n < NUM_EXTRA_CODE; n++) {
    if (extra_code(n) && isdeclare(extra_code(n)))
      write_declare("%s", extra_code(n));
  }
  if (callback() && is_name(callback()))
    write_declare("extern void %s(%s*, %s);", callback(), t,
		  user_data_type() ? user_data_type() : "void*");
  const char* c = array_name(this);
  const char* k = class_name(1);
  if (c && !k) {
    write_c("\n");
    if (!public_) write_c("static ");
    else write_h("extern %s *%s;\n", t, c);
    if (strchr(c, '[') == NULL) write_c("%s *%s=(%s *)0;\n", t, c, t);
    else write_c("%s *%s={(%s *)0};\n", t, c, t);
  }
  if (callback() && !is_name(callback())) {
    // see if 'o' or 'v' used, to prevent unused argument warnings:
    int use_o = 0;
    int use_v = 0;
    const char *d;
    for (d = callback(); *d;) {
      if (*d == 'o' && !is_id(d[1])) use_o = 1;
      if (*d == 'v' && !is_id(d[1])) use_v = 1;
      do d++; while (is_id(*d));
      while (*d && !is_id(*d)) d++;
    }
    const char* cn = callback_name();
    if (k) {
      write_c("\ninline void %s::%s_i(%s*", k, cn, t);
    } else {
      write_c("\nstatic void %s(%s*", cn, t);
    }
    if (use_o) write_c(" o");
    const char* ut = user_data_type() ? user_data_type() : "void*";
    write_c(", %s", ut);
    if (use_v) write_c(" v");
    write_c(") {\n  %s", callback());
    if (*(d-1) != ';') {
      const char *p = strrchr(callback(), '\n');
      if (p) p ++;
      else p = callback();
      // Only add trailing semicolon if the last line is not a preprocessor
      // statement...
      if (*p != '#' && *p) write_c(";");
    }
    write_c("\n}\n");
    if (k) {
      write_c("void %s::%s(%s* o, %s v) {\n", k, cn, t, ut);
      write_c("  ((%s*)(o->", k);
      for (Fl_Type* p = parent; p->is_widget(); p = p->parent)
	write_c("parent()->");
      write_c("user_data()))->%s_i(o,v);\n}\n", cn);
    }
  }
  if (image) {
    if (image->written != write_number) {
      image->write_static();
      image->written = write_number;
    }
  }
  if (inactive) {
    if (inactive->written != write_number) {
      inactive->write_static();
      inactive->written = write_number;
    }
  }
}

const char *Fl_Type::callback_name() {
  if (is_name(callback())) return callback();
  return unique_id(this, "cb", name(), label());
}

extern int varused_test, varused;
  
void Fl_Widget_Type::write_code1() {
  const char* t = subclassname(this);
  const char *c = array_name(this);
  if (c) {
    if (class_name(1)) {
      write_public(public_);
      write_h("  %s *%s;\n", t, c);
    }
  }
  if (class_name(1) && callback() && !is_name(callback())) {
    const char* cn = callback_name();
    const char* ut = user_data_type() ? user_data_type() : "void*";
    write_public(0);
    write_h("  inline void %s_i(%s*, %s);\n", cn, t, ut);
    write_h("  static void %s(%s*, %s);\n", cn, t, ut);
  }
  // figure out if local varaible will be used (prevent compiler warnings):
  if (is_parent())
    varused = 1;
  else {
    varused_test = 1; varused = 0;
    write_widget_code();
    varused_test = 0;
    for (int n=0; n < NUM_EXTRA_CODE; n++)
      if (extra_code(n) && !isdeclare(extra_code(n))) varused = 1;
  }
  write_c(indent());
  if (varused) write_c("{ %s* o = ", t);
  if (name()) write_c("%s = ", name());
  if (is_window()) {
    // Handle special case where user is faking a Fl_Group type as a window,
    // there is no 2-argument constructor in that case:
    if (!strstr(t, "Window"))
      write_c("new %s(0, 0, %d, %d", t, o->w(), o->h());
    else
      write_c("new %s(%d, %d", t, o->w(), o->h());
  } else {
    write_c("new %s(%d, %d, %d, %d", t, o->x(), o->y(), o->w(), o->h());
  }
  if (label() && *label()) {
    write_c(", ");
    switch (i18n_type) {
    case 0 : /* None */
        write_cstring(label());
        break;
    case 1 : /* GNU gettext */
        write_c("%s(", i18n_function);
        write_cstring(label());
	write_c(")");
        break;
    case 2 : /* POSIX catgets */
        write_c("catgets(%s,%s,%d,", i18n_file[0] ? i18n_file : "_catalog",
	        i18n_set, msgnum());
        write_cstring(label());
	write_c(")");
        break;
    }
  }
  write_c(");\n");
  indentation += 2;

  if (is_window()) write_c("%sw = o;\n",indent());
  if (varused) write_widget_code();
}

// this is split from write_code1() for Fl_Window_Type:
void Fl_Widget_Type::write_widget_code() {
  Fl_Widget* tplate = ((Fl_Widget_Type*)factory)->o;
  if (tooltip() && *tooltip()) {
    write_c("%so->tooltip(",indent());
    switch (i18n_type) {
    case 0 : /* None */
        write_cstring(tooltip());
        break;
    case 1 : /* GNU gettext */
        write_c("%s(", i18n_function);
        write_cstring(tooltip());
	write_c(")");
        break;
    case 2 : /* POSIX catgets */
        write_c("catgets(%s,%s,%d,", i18n_file[0] ? i18n_file : "_catalog",
	        i18n_set, msgnum() + 1);
        write_cstring(tooltip());
	write_c(")");
        break;
    }
    write_c(");\n");
  }

  if (o->type() != tplate->type() && !is_window())
    write_c("%so->type(%d);\n", indent(), o->type());
  if (o->box() != tplate->box() || subclass())
    write_c("%so->box(FL_%s);\n", indent(), boxname(o->box()));
  if (is_button()) {
    Fl_Button* b = (Fl_Button*)o;
    if (b->down_box()) write_c("%so->down_box(FL_%s);\n", indent(),
			       boxname(b->down_box()));
    if (b->value()) write_c("%so->value(1);\n", indent());
    if (b->shortcut())
      write_c("%so->shortcut(0x%x);\n", indent(), b->shortcut());
  }
  if (is_menu_button()) {
    Fl_Menu_* b = (Fl_Menu_*)o;
    if (b->down_box()) write_c("%so->down_box(FL_%s);\n", indent(),
			       boxname(b->down_box()));
  }
  if (o->color() != tplate->color() || subclass())
    write_c("%so->color(%d);\n", indent(), o->color());
  if (o->selection_color() != tplate->selection_color() || subclass())
    write_c("%so->selection_color(%d);\n", indent(), o->selection_color());
  if (image) image->write_code();
  if (inactive) inactive->write_code(1);
  if (o->labeltype() != tplate->labeltype() || subclass())
    write_c("%so->labeltype(FL_%s);\n", indent(),
	    item_name(labeltypemenu, o->labeltype()));
  if (o->labelfont() != tplate->labelfont() || subclass())
    write_c("%so->labelfont(%d);\n", indent(), o->labelfont());
  if (o->labelsize() != tplate->labelsize() || subclass())
    write_c("%so->labelsize(%d);\n", indent(), o->labelsize());

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?