Chinaunix首页 | 论坛 | 博客
  • 博客访问: 6597026
  • 博文数量: 227
  • 博客积分: 10047
  • 博客等级: 上将
  • 技术积分: 6678
  • 用 户 组: 普通用户
  • 注册时间: 2006-07-11 10:33
个人简介

网上的蜘蛛

文章分类

全部博文(227)

文章存档

2010年(19)

2009年(29)

2008年(179)

分类: C/C++

2008-12-20 15:22:34

I have been playing with some ideas to compartmentalize my FLTK applications and a member at asked about how to extend your own widget classes. So I, in my over the top way, designed a UI that will work with a infinite array Phone Book I wrote. The PBook is not implemented yet but the UI is designed. All that is left is to create the remaining callbacks and interface it with the PBook class.

There are a lot of little things that may be of interest.

  1. A simple how to for deriving classes and using those classes as original fltk types.

  2. In class callbacks.

  3. Exiting without calling exit().

  4. Reusable custom widgets.

  5. Flicker protector group.

  6. Menu array pointers.

  7. Now, that being said, this is not even vaguely complete. The phone book portion is still in console form and it was rudementary at best. It is based on a self extending concept that builds a page of objects at a time and uses an overloaded operator[] for indexing. Currently it is a singly linked list. To be useful it will need to become doubly linked and have a current pointer added.

    The idea is to have the UI have two views. A single entry and a page of entries that matches the paging system of the PBook . It should have simple sorting based on one of the fields in the record. Nothing ground-breaking but it seemed both simple and interesting enough for the real project, which was trying to get reusability and ease of creation for FLTK widgets. Simple things but hopefully very useful in the long run. It will also serve to give someone starting with FLTK some room to improve on their own.

    Now, I'm not exactly a professional at this so feel free to point out ways that this could be done better. One thing that concerns me is the data base object. It seems to make sense that it would be seperately maintained from the UI. From within the UI I can always find my way back to the main window (see the exit menu callback) but I am not entirely sure how I will handle the database itself. Working within FLTK's event loop still gives me a bit of a headache sometimes. One of the nice things about it though is that FLTK works with C++ code and has a very straightforward method of get/put using overloading the return type which I use in the phone book portion of the code.

    Well, that's about enough for an introduction. In order to build this you will need to have FLTK 1.1.x installed and use the command line:

    Generic Code Example:

    g++ -Wall fltkPBook_UI.cpp PBookMenu.cpp PBookGroups.cpp MyWidgets.cpp `fltk-config --ldflags --cxxflags` -s -o fltkPBook
    

    I have built it with the current subversion repo on Windows 2000 using the CygWin GNU tools. It should be portable especially in it's current state as I try to use the C++ standard and no STL. I do like to use though so that is the only place I can think of being a problem. When I get to it I will post the working version of the project. If anyone wants to pitch in, feel free. Any OOP comentary will be most welcome as well. Here is what it currently looks like.

    Enjoy.

    Mark

    fltkPBook_UI.cpp

///////////////fltkPBook_UI.cpp///////////////////


#include "fltkPBook_UI.h"

#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Enumerations.H>

PBookUI::PBookUI(const char* L) : Fl_Double_Window(0, 0, 340, 160, L) {

  free_position();
  callback(cb_exit,this);
  color(FL_BACKGROUND_COLOR);
  selection_color(FL_BACKGROUND_COLOR);
  labelfont(0);
  align(FL_ALIGN_TOP);

  add(menu_bar);
  add(entry_group);
  add(butbar_group);
  add(nav_group);

  end();
}


// BELOW here should become part of its own .cpp file

int main(int argc, char* argv[]){

  Fl::visual(FL_DOUBLE|FL_INDEX);
  PBookAPP PBook;
  PBook.Show(argc, argv);
  return(Fl::run());
}

fltkPBook_UI.h

///////////////PBookMenu.h///////////////////


#if !defined __PBOOKMENU_H__
#define __PBOOKMENU_H__

#include <FL/Fl.H>
#include <FL/Fl_Menu_Bar.H>
#include <FL/Fl_Menu_Item.H>
#include <FL/Fl_Widget.H>
#include <FL/Fl_Double_Window.H>

class MenuMB : public Fl_Menu_Bar {

  public:
    MenuMB();
    ~MenuMB(){};

  private:
    enum {PBOOK = 0, FLTK, FREE};

    void icb_new(){};
    static void cb_new(Fl_Widget*, void* user)
      { ((MenuMB*)user)->icb_new(); };
    void icb_load(){};
    static void cb_load(Fl_Widget*, void* user)
      { ((MenuMB*)user)->icb_load(); };
    void icb_save(){};
    static void cb_save(Fl_Widget*, void* user)
      { ((MenuMB*)user)->icb_save(); };
    void icb_exit(Fl_Widget* w) {
      w->window()->hide();
    };
    static void cb_exit(Fl_Widget* w, void* user)
      { ((MenuMB*)user)->icb_exit(w); };
    static void cb_about(Fl_Widget*, void* user);

    static Fl_Menu_Item menu_main[];
    static Fl_Menu_Item menu_file[];
    static Fl_Menu_Item menu_about[];
      static Fl_Menu_Item* new_menu;
      static Fl_Menu_Item* load_menu;
      static Fl_Menu_Item* save_menu;
      static Fl_Menu_Item* exit_menu;
      static Fl_Menu_Item* about_pbook;
      static Fl_Menu_Item* about_fltk;
      static Fl_Menu_Item* about_free;
};

#endif

PBookGroups.cpp

///////////////PBookGroups.cpp///////////////////


#include "PBookGroups.h"
#include <FL/Fl.H>
#include <FL/Fl_Group.H>
#include <FL/Enumerations.H>

EntryGP::EntryGP() : Fl_Group(0, 20, 340, 100),
                     name_box(10, 30, 70, 20, "Name :"),
                   number_box(10, 60, 70, 20, "Number :"),
                    where_box(10, 90, 70, 20, "Where :"),
                     name_out(90, 30, 240, 20),
                   number_out(90, 60, 240, 20),
                    where_out(90, 90, 240, 20),
             entry_hide_group(x(), y(), w(), h()) {

  box(FL_ENGRAVED_FRAME);
  when(FL_WHEN_RELEASE);
  
  add(name_box);
  add(number_box);
  add(where_box);
  add(name_out);
  add(number_out);
  add(where_out);
  add(entry_hide_group);

  end();
}


ButBarGP::ButBarGP() : Fl_Group(0, 120, 340, 20),
                    edit_button(0, y(), 85, h(), "Edit"),
                    page_button(85, y(), 85, h(), "page view"),
                  cancel_button(170, y(), 85, h(), "cancel"),
                  modify_button(255, y(), 85, h(), "modify") {

  box(FL_ENGRAVED_FRAME);
  when(FL_WHEN_RELEASE);

  add(edit_button);
  add(page_button);
  add(page_button);
  add(modify_button);

  end();
}

NavGP::NavGP() : Fl_Group(0, 140, 340, 20),
                 name_button(0, y(), 70, h(), "Name"),
                 number_button(70, y(), 70, h(), "Number"),
                 where_button(140, y(), 70, h(), "Where"),
                 back_button(210, y(), 65, h(), "@<-"),
                 next_button(275, y(), 65, h(), "@->") {

  when(FL_WHEN_RELEASE);
  box(FL_ENGRAVED_FRAME);

  // These are a radio group

  add(name_button);
  add(number_button);
  add(where_button);
  // Pick a default on

  name_button.setonly();
  
  add(back_button);
  add(next_button);

  end();
}

PBookGroups.h

 

///////////////PBookGroups.h///////////////////


#if !defined __PBOOKGROUPS_H__
#define __PBOOKGROUPS_H__

#include "MyWidgets.h"
#include <FL/Fl.H>
#include <FL/Fl_Group.H>


class EntryGP : public Fl_Group {

  public:
    EntryGP();
    ~EntryGP(){};

  private:
    StandardLBL name_box;
    StandardLBL number_box;
    StandardLBL where_box;
    StandardOUT name_out;
    StandardOUT number_out;
    StandardOUT where_out;
    ScreenGP entry_hide_group;
};


class ButBarGP : public Fl_Group {

  public:
    ButBarGP();
    ~ButBarGP(){};

  private:
    LightImpBUT edit_button;
    StandardBUT page_button;
    StandardBUT cancel_button;
    ReturnBUT modify_button;
};


class NavGP : public Fl_Group {

  public:
    NavGP();
    ~NavGP(){};

  private:
    LightRadioBUT name_button;
    LightRadioBUT number_button;
    LightRadioBUT where_button;
    StandardBUT back_button;
    StandardBUT next_button;
};

#endif

MyWidgets.cpp

#include <FL/Fl_Button.H>
#include <FL/Fl_Return_Button.H>
#include <Fl/fl_draw.H>
#include <FL/Enumerations.H>

LightRadioBUT::LightRadioBUT(int X, int Y, int W, int H, const char* L)
           : Fl_Light_Button(X, Y, W, H, L) {

  type(FL_RADIO_BUTTON);
  box(FL_THIN_UP_BOX);
  selection_color(fl_darker(FL_GREEN));
  labeltype(FL_ENGRAVED_LABEL);
  labelcolor(fl_darker(FL_BLUE));
  align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
  when(FL_WHEN_RELEASE);
}


LightImpBUT::LightImpBUT(int X, int Y, int W, int H, const char* L)
           : Fl_Light_Button(X, Y, W, H, L) {

  box(FL_THIN_UP_BOX);
  selection_color(FL_RED);
  labeltype(FL_ENGRAVED_LABEL);
  labelcolor(fl_darker(FL_BLUE));
  align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
  when(FL_WHEN_RELEASE);
}


StandardBUT::StandardBUT(int X, int Y, int W, int H, const char* L)
              : Fl_Button(X, Y, W, H, L) {

  box(FL_THIN_UP_BOX);
  down_box(FL_THIN_DOWN_BOX);
  labeltype(FL_ENGRAVED_LABEL);
  labelcolor(fl_darker(FL_BLUE));
  align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
  when(FL_WHEN_RELEASE);
}


ReturnBUT::ReturnBUT(int X, int Y, int W, int H, const char* L)
              : Fl_Return_Button(X, Y, W, H, L) {

  box(FL_THIN_UP_BOX);
  down_box(FL_THIN_DOWN_BOX);
  labeltype(FL_ENGRAVED_LABEL);
  labelcolor(fl_darker(FL_BLUE));
  align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
  when(FL_WHEN_RELEASE);
}


int ReturnBUT::fl_return_arrow(int x, int y, int w, int h) {
  int size = w; if (h<size) size = h;
  int d = (size+2)/4; if (d<3) d = 3;
  int t = (size+9)/12; if (t<1) t = 1;
  int x0 = x+(w-2*d-2*t-1)/2;
  int x1 = x0+d;
  int y0 = y+h/2;
  
  fl_color(fl_darker(FL_BLUE));
  fl_begin_polygon();
    fl_vertex(x0, y0);
    fl_vertex(x1, y0+d);
    fl_vertex(x1, y0+t);
    fl_vertex(x1+d+2*t, y0+t);
    fl_vertex(x1+d+2*t, y0-d);
    fl_vertex(x1+d, y0-d);
    fl_vertex(x1+d, y0-t);
    fl_vertex(x1+1, y0-t);
    fl_vertex(x1, y0-t);
    fl_vertex(x1, y0-d);
    fl_vertex(x0, y0);
  fl_end_polygon();

  fl_color(fl_lighter(FL_BLUE));
  fl_line(x0, y0, x1, y0+d);
  fl_yxline(x1, y0+d, y0+t, x1+d+2*t,y0-d);
  fl_color(fl_darker(FL_BLUE));
  fl_xyline(x1+d+2*t,y0-d, x1+d, y0-t, x1+1);
  fl_color(fl_lighter(FL_BLUE));
  fl_line(x1, y0-t, x1, y0-d);
  fl_color(fl_darker(FL_BLUE));
  fl_line(x1, y0-d, x0, y0);

  return 1;
}

void ReturnBUT::draw() {
  if (type() == FL_HIDDEN_BUTTON) return;
  draw_box(value() ? (down_box()?down_box():fl_down(box())) : box(),
     value() ? selection_color() : color());
  int W = h();
  if (w()/3 < W) W = w()/3;
  fl_return_arrow(x()+w()-W-4, y(), W, h());
  draw_label(x(), y(), w()-W+4, h());
  if (Fl::focus() == this) draw_focus();
}


StandardLBL::StandardLBL(int X, int Y, int W, int H, const char* L)
              : Fl_Box(X, Y, W, H, L) {

  labeltype(FL_EMBOSSED_LABEL);
  labelcolor(FL_BLUE);
  align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE);
  when(FL_WHEN_NEVER);
}


StandardOUT::StandardOUT(int X, int Y, int W, int H)
             : Fl_Output(X, Y, W, H) {

  labeltype(FL_NO_LABEL);
  when(FL_WHEN_NEVER);
}


ScreenGP::ScreenGP(int X, int Y, int W, int H)
             : Fl_Group(X, Y, W, H) {

  box(FL_NO_BOX);
  labeltype(FL_NO_LABEL);
  when(FL_WHEN_NEVER);
  deactivate();
  
  end();
}

MyWidgets.h

 

///////////////MyWidgets.h///////////////////


#if !defined __MYWIDGETS_H__
#define __MYWIDGETS_H__

#include <FL/Fl.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Output.H>
#include <FL/Fl_Light_Button.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Return_Button.H>
#include <FL/Fl_Group.H>

class LightRadioBUT : public Fl_Light_Button {

  public:
    LightRadioBUT(int X, int Y, int W, int H, const char* L);
    ~LightRadioBUT(){};
};


class LightImpBUT : public Fl_Light_Button {

  public:
    LightImpBUT(int X, int Y, int W, int H, const char* L);
    ~LightImpBUT(){};
};


class StandardBUT : public Fl_Button {

  public:
    StandardBUT(int X, int Y, int W, int H, const char* L);
    ~StandardBUT(){};
};


class ReturnBUT : public Fl_Return_Button {

  public:
    ReturnBUT(int X, int Y, int W, int H, const char* L);
    ~ReturnBUT(){};
  
  private:
    int fl_return_arrow(int x, int y, int w, int h);
    void draw();
};


class StandardLBL : public Fl_Box {

  public:
    StandardLBL(int X, int Y, int W, int H, const char* L);
    ~StandardLBL(){};
};


class StandardOUT : public Fl_Output {

  public:
    StandardOUT(int X, int Y, int W, int H);
    ~StandardOUT(){};
};


class ScreenGP : public Fl_Group {

  public:
    ScreenGP(int X, int Y, int W, int H);
    ~ScreenGP(){};
};

#endif

阅读(6694) | 评论(2) | 转发(0) |
0

上一篇:路-->江南

下一篇:C++中Txt文件读取和写入

给主人留下些什么吧!~~

zhaorongsu2008-12-20 19:22:11

这就是传说中的....呀

zhaorongsu2008-12-20 19:21:59

这就是传说中的....呀