Initial import of Dillo
This commit is contained in:
539
dw/fltkui.hh
Normal file
539
dw/fltkui.hh
Normal file
@ -0,0 +1,539 @@
|
||||
#ifndef __DW_FLTK_UI_HH__
|
||||
#define __DW_FLTK_UI_HH__
|
||||
|
||||
#ifndef __INCLUDED_FROM_DW_FLTK_CORE_HH__
|
||||
# error Do not include this file directly, use "fltkcore.hh" instead.
|
||||
#endif
|
||||
|
||||
#include <FL/Fl_Button.H>
|
||||
#include <FL/Fl_Menu.H>
|
||||
#include <FL/Fl_Text_Buffer.H>
|
||||
|
||||
namespace dw {
|
||||
namespace fltk {
|
||||
|
||||
/**
|
||||
* \brief FLTK implementation of dw::core::ui.
|
||||
*
|
||||
* <div style="border: 2px solid #ff0000; margin-top: 0.5em;
|
||||
* margin-bottom: 0.5em; padding: 0.5em 1em;
|
||||
* background-color: #ffefe0"><b>Update:</b> The complicated design
|
||||
* results from my insufficient knowledge of C++ some years ago; since
|
||||
* then, I've learned how to deal with "diamond inheritance", as the
|
||||
* (ideal, not actually implemented) design in the first diagram
|
||||
* shows. It should be possible to implement this ideal design in a
|
||||
* straightforward way, and so get rid of templates. --SG</div>
|
||||
*
|
||||
* The design should be like this:
|
||||
*
|
||||
* \dot
|
||||
* digraph G {
|
||||
* node [shape=record, fontname=Helvetica, fontsize=10];
|
||||
* edge [arrowhead="none", arrowtail="empty", dir="both",
|
||||
* labelfontname=Helvetica, labelfontsize=10, color="#404040",
|
||||
* labelfontcolor="#000080"];
|
||||
* fontname=Helvetica; fontsize=10;
|
||||
*
|
||||
* subgraph cluster_core {
|
||||
* style="dashed"; color="#000080"; fontname=Helvetica; fontsize=10;
|
||||
* label="dw::core::ui";
|
||||
*
|
||||
* Resource [color="#a0a0a0", URL="\ref dw::core::ui::Resource"];
|
||||
* LabelButtonResource [color="#a0a0a0",
|
||||
* URL="\ref dw::core::ui::LabelButtonResource"];
|
||||
* EntryResource [color="#a0a0a0",
|
||||
* URL="\ref dw::core::ui::EntryResource"];
|
||||
* }
|
||||
*
|
||||
* subgraph cluster_fltk {
|
||||
* style="dashed"; color="#000080"; fontname=Helvetica; fontsize=10;
|
||||
* label="dw::fltk::ui";
|
||||
*
|
||||
* FltkResource [color="#a0a0a0", URL="\ref dw::fltk::ui::FltkResource"];
|
||||
* FltkLabelButtonResource
|
||||
* [URL="\ref dw::fltk::ui::FltkLabelButtonResource"];
|
||||
* FltkEntryResource [URL="\ref dw::fltk::ui::FltkEntryResource"];
|
||||
* }
|
||||
*
|
||||
* Resource -> LabelButtonResource;
|
||||
* Resource -> EntryResource;
|
||||
* FltkResource -> FltkLabelButtonResource;
|
||||
* FltkResource -> FltkEntryResource;
|
||||
* Resource -> FltkResource;
|
||||
* LabelButtonResource -> FltkLabelButtonResource;
|
||||
* EntryResource -> FltkEntryResource;
|
||||
* }
|
||||
* \enddot
|
||||
*
|
||||
* <center>[\ref uml-legend "legend"]</center>
|
||||
*
|
||||
* where dw::fltk::ui::FltkResource provides some base functionality for all
|
||||
* conctrete FLTK implementations of sub-interfaces of dw::core::ui::Resource.
|
||||
* However, this is not directly possible in C++, since the base class
|
||||
* dw::core::ui::Resource is ambiguous for
|
||||
* dw::fltk::ui::FltkLabelButtonResource.
|
||||
*
|
||||
* To solve this, we have to remove the dependency between
|
||||
* dw::fltk::ui::FltkResource and dw::core::ui::Resource, instead, the part
|
||||
* of dw::core::ui::Resource, which is implemented in
|
||||
* dw::fltk::ui::FltkResource, must be explicitly delegated from
|
||||
* dw::fltk::ui::FltkLabelButtonResourceto dw::fltk::ui::FltkResource:
|
||||
*
|
||||
* \dot
|
||||
* digraph G {
|
||||
* node [shape=record, fontname=Helvetica, fontsize=10];
|
||||
* edge [arrowhead="none", arrowtail="empty", dir="both",
|
||||
* labelfontname=Helvetica, labelfontsize=10, color="#404040",
|
||||
* labelfontcolor="#000080"];
|
||||
* fontname=Helvetica; fontsize=10;
|
||||
*
|
||||
* subgraph cluster_core {
|
||||
* style="dashed"; color="#000080"; fontname=Helvetica; fontsize=10;
|
||||
* label="dw::core::ui";
|
||||
*
|
||||
* Resource [color="#a0a0a0", URL="\ref dw::core::ui::Resource"];
|
||||
* LabelButtonResource [color="#a0a0a0",
|
||||
* URL="\ref dw::core::ui::LabelButtonResource"];
|
||||
* EntryResource [color="#a0a0a0",
|
||||
* URL="\ref dw::core::ui::EntryResource"];
|
||||
* }
|
||||
*
|
||||
* subgraph cluster_fltk {
|
||||
* style="dashed"; color="#000080"; fontname=Helvetica; fontsize=10;
|
||||
* label="dw::fltk::ui";
|
||||
*
|
||||
* FltkResource [color="#a0a0a0", URL="\ref dw::fltk::ui::FltkResource"];
|
||||
* FltkLabelButtonResource
|
||||
* [URL="\ref dw::fltk::ui::FltkLabelButtonResource"];
|
||||
* FltkEntryResource [URL="\ref dw::fltk::ui::FltkEntryResource"];
|
||||
* }
|
||||
*
|
||||
* Resource -> LabelButtonResource;
|
||||
* Resource -> EntryResource;
|
||||
* FltkResource -> FltkLabelButtonResource;
|
||||
* FltkResource -> FltkEntryResource;
|
||||
* LabelButtonResource -> FltkLabelButtonResource;
|
||||
* EntryResource -> FltkEntryResource;
|
||||
* }
|
||||
* \enddot
|
||||
*
|
||||
* <center>[\ref uml-legend "legend"]</center>
|
||||
*
|
||||
* To make this a bit simpler, we use templates:
|
||||
*
|
||||
* \dot
|
||||
* digraph G {
|
||||
* node [shape=record, fontname=Helvetica, fontsize=10];
|
||||
* edge [arrowhead="none", arrowtail="empty", dir="both",
|
||||
* labelfontname=Helvetica, labelfontsize=10, color="#404040",
|
||||
* labelfontcolor="#000080"];
|
||||
* fontname=Helvetica; fontsize=10;
|
||||
*
|
||||
* subgraph cluster_core {
|
||||
* style="dashed"; color="#000080"; fontname=Helvetica; fontsize=10;
|
||||
* label="dw::core::ui";
|
||||
*
|
||||
* Resource [color="#a0a0a0", URL="\ref dw::core::ui::Resource"];
|
||||
* LabelButtonResource [color="#a0a0a0",
|
||||
* URL="\ref dw::core::ui::LabelButtonResource"];
|
||||
* EntryResource [color="#a0a0a0",
|
||||
* URL="\ref dw::core::ui::EntryResource"];
|
||||
* }
|
||||
*
|
||||
* subgraph cluster_fltk {
|
||||
* style="dashed"; color="#000080"; fontname=Helvetica; fontsize=10;
|
||||
* label="dw::fltk::ui";
|
||||
*
|
||||
* FltkResource [color="#a0a0a0", URL="\ref dw::fltk::ui::FltkResource"];
|
||||
* FltkSpecificResource [color="#a0a0a0",
|
||||
* fillcolor="#ffffc0", style="filled"
|
||||
* URL="\ref dw::fltk::ui::FltkSpecificResource"];
|
||||
* FltkSpecificResource_button [color="#a0a0a0",
|
||||
* label="FltkSpecificResource \<LabelButtonResource\>"];
|
||||
* FltkSpecificResource_entry [color="#a0a0a0",
|
||||
* label="FltkSpecificResource \<EntryResource\>"];
|
||||
* FltkEntryResource [URL="\ref dw::fltk::ui::FltkEntryResource"];
|
||||
* FltkLabelButtonResource
|
||||
* [URL="\ref dw::fltk::ui::FltkLabelButtonResource"];
|
||||
* }
|
||||
*
|
||||
* Resource -> LabelButtonResource;
|
||||
* Resource -> EntryResource;
|
||||
* FltkResource -> FltkSpecificResource;
|
||||
* FltkSpecificResource -> FltkSpecificResource_button [arrowhead="open",
|
||||
* arrowtail="none",
|
||||
* dir="both",
|
||||
* style="dashed",
|
||||
* color="#808000"];
|
||||
* FltkSpecificResource -> FltkSpecificResource_entry [arrowhead="open",
|
||||
* arrowtail="none",
|
||||
* dir="both",
|
||||
* style="dashed",
|
||||
* color="#808000"];
|
||||
* LabelButtonResource -> FltkSpecificResource_button;
|
||||
* EntryResource -> FltkSpecificResource_entry;
|
||||
* FltkSpecificResource_button -> FltkLabelButtonResource;
|
||||
* FltkSpecificResource_entry -> FltkEntryResource;
|
||||
* }
|
||||
* \enddot
|
||||
*
|
||||
* <center>[\ref uml-legend "legend"]</center>
|
||||
*/
|
||||
namespace ui {
|
||||
|
||||
/**
|
||||
* ...
|
||||
*/
|
||||
class FltkResource: public lout::object::Object
|
||||
{
|
||||
private:
|
||||
bool enabled;
|
||||
|
||||
protected:
|
||||
FltkView *view;
|
||||
Fl_Widget *widget;
|
||||
core::Allocation allocation;
|
||||
FltkPlatform *platform;
|
||||
|
||||
core::style::Style *style;
|
||||
|
||||
FltkResource (FltkPlatform *platform);
|
||||
void init (FltkPlatform *platform);
|
||||
virtual Fl_Widget *createNewWidget (core::Allocation *allocation) = 0;
|
||||
|
||||
virtual void setWidgetStyle (Fl_Widget *widget, core::style::Style *style);
|
||||
void setDisplayed (bool displayed);
|
||||
bool displayed();
|
||||
public:
|
||||
~FltkResource ();
|
||||
|
||||
virtual void attachView (FltkView *view);
|
||||
virtual void detachView (FltkView *view);
|
||||
|
||||
void sizeAllocate (core::Allocation *allocation);
|
||||
void draw (core::View *view, core::Rectangle *area,
|
||||
core::DrawingContext *context);
|
||||
|
||||
void setStyle (core::style::Style *style);
|
||||
|
||||
bool isEnabled ();
|
||||
void setEnabled (bool enabled);
|
||||
};
|
||||
|
||||
|
||||
template <class I> class FltkSpecificResource: public I, public FltkResource
|
||||
{
|
||||
public:
|
||||
FltkSpecificResource (FltkPlatform *platform);
|
||||
~FltkSpecificResource ();
|
||||
|
||||
void sizeAllocate (core::Allocation *allocation);
|
||||
void draw (core::View *view, core::Rectangle *area,
|
||||
core::DrawingContext *context);
|
||||
void setStyle (core::style::Style *style);
|
||||
|
||||
bool isEnabled ();
|
||||
void setEnabled (bool enabled);
|
||||
};
|
||||
|
||||
|
||||
class FltkLabelButtonResource:
|
||||
public FltkSpecificResource <dw::core::ui::LabelButtonResource>
|
||||
{
|
||||
private:
|
||||
const char *label;
|
||||
|
||||
static void widgetCallback (Fl_Widget *widget, void *data);
|
||||
|
||||
protected:
|
||||
Fl_Widget *createNewWidget (core::Allocation *allocation);
|
||||
|
||||
public:
|
||||
FltkLabelButtonResource (FltkPlatform *platform, const char *label);
|
||||
~FltkLabelButtonResource ();
|
||||
|
||||
void sizeRequest (core::Requisition *requisition);
|
||||
|
||||
const char *getLabel ();
|
||||
void setLabel (const char *label);
|
||||
};
|
||||
|
||||
|
||||
class FltkComplexButtonResource:
|
||||
public FltkSpecificResource <dw::core::ui::ComplexButtonResource>
|
||||
{
|
||||
private:
|
||||
bool relief;
|
||||
|
||||
static void widgetCallback (Fl_Widget *widget, void *data);
|
||||
|
||||
protected:
|
||||
FltkView *topView, *flatView;
|
||||
|
||||
void attachView (FltkView *view);
|
||||
void detachView (FltkView *view);
|
||||
|
||||
void sizeAllocate (core::Allocation *allocation);
|
||||
|
||||
dw::core::Platform *createPlatform ();
|
||||
void setLayout (dw::core::Layout *layout);
|
||||
|
||||
int reliefXThickness ();
|
||||
int reliefYThickness ();
|
||||
|
||||
Fl_Widget *createNewWidget (core::Allocation *allocation);
|
||||
|
||||
public:
|
||||
FltkComplexButtonResource (FltkPlatform *platform, dw::core::Widget *widget,
|
||||
bool relief);
|
||||
~FltkComplexButtonResource ();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \bug Maximal length not supported yet.
|
||||
* \todo Text values are not synchronized (not needed in dillo).
|
||||
*/
|
||||
class FltkEntryResource:
|
||||
public FltkSpecificResource <dw::core::ui::EntryResource>
|
||||
{
|
||||
private:
|
||||
int size;
|
||||
bool password;
|
||||
const char *initText;
|
||||
char *label;
|
||||
int label_w;
|
||||
char *placeholder;
|
||||
bool editable;
|
||||
|
||||
static void widgetCallback (Fl_Widget *widget, void *data);
|
||||
void setDisplayed (bool displayed);
|
||||
|
||||
protected:
|
||||
Fl_Widget *createNewWidget (core::Allocation *allocation);
|
||||
void setWidgetStyle (Fl_Widget *widget, core::style::Style *style);
|
||||
|
||||
public:
|
||||
FltkEntryResource (FltkPlatform *platform, int size, bool password,
|
||||
const char *label, const char *placeholder);
|
||||
~FltkEntryResource ();
|
||||
|
||||
void sizeRequest (core::Requisition *requisition);
|
||||
void sizeAllocate (core::Allocation *allocation);
|
||||
|
||||
const char *getText ();
|
||||
void setText (const char *text);
|
||||
bool isEditable ();
|
||||
void setEditable (bool editable);
|
||||
void setMaxLength (int maxlen);
|
||||
};
|
||||
|
||||
|
||||
class FltkMultiLineTextResource:
|
||||
public FltkSpecificResource <dw::core::ui::MultiLineTextResource>
|
||||
{
|
||||
private:
|
||||
bool editable;
|
||||
int numCols, numRows;
|
||||
char *placeholder;
|
||||
protected:
|
||||
Fl_Widget *createNewWidget (core::Allocation *allocation);
|
||||
void setWidgetStyle (Fl_Widget *widget, core::style::Style *style);
|
||||
|
||||
public:
|
||||
FltkMultiLineTextResource (FltkPlatform *platform, int cols, int rows,
|
||||
const char *placeholder);
|
||||
~FltkMultiLineTextResource ();
|
||||
|
||||
void sizeRequest (core::Requisition *requisition);
|
||||
|
||||
const char *getText ();
|
||||
void setText (const char *text);
|
||||
bool isEditable ();
|
||||
void setEditable (bool editable);
|
||||
};
|
||||
|
||||
|
||||
template <class I> class FltkToggleButtonResource:
|
||||
public FltkSpecificResource <I>
|
||||
{
|
||||
private:
|
||||
bool initActivated;
|
||||
|
||||
protected:
|
||||
virtual Fl_Button *createNewButton (core::Allocation *allocation) = 0;
|
||||
Fl_Widget *createNewWidget (core::Allocation *allocation);
|
||||
void setWidgetStyle (Fl_Widget *widget, core::style::Style *style);
|
||||
|
||||
public:
|
||||
FltkToggleButtonResource (FltkPlatform *platform,
|
||||
bool activated);
|
||||
~FltkToggleButtonResource ();
|
||||
|
||||
void sizeRequest (core::Requisition *requisition);
|
||||
|
||||
bool isActivated ();
|
||||
void setActivated (bool activated);
|
||||
};
|
||||
|
||||
|
||||
class FltkCheckButtonResource:
|
||||
public FltkToggleButtonResource <dw::core::ui::CheckButtonResource>
|
||||
{
|
||||
protected:
|
||||
Fl_Button *createNewButton (core::Allocation *allocation);
|
||||
|
||||
public:
|
||||
FltkCheckButtonResource (FltkPlatform *platform,
|
||||
bool activated);
|
||||
~FltkCheckButtonResource ();
|
||||
};
|
||||
|
||||
|
||||
class FltkRadioButtonResource:
|
||||
public FltkToggleButtonResource <dw::core::ui::RadioButtonResource>
|
||||
{
|
||||
private:
|
||||
class Group
|
||||
{
|
||||
private:
|
||||
class FltkGroupIterator:
|
||||
public dw::core::ui::RadioButtonResource::GroupIterator
|
||||
{
|
||||
private:
|
||||
lout::container::typed::Iterator <FltkRadioButtonResource> it;
|
||||
|
||||
public:
|
||||
inline FltkGroupIterator (lout::container::typed::List
|
||||
<FltkRadioButtonResource>
|
||||
*list)
|
||||
{ it = list->iterator (); }
|
||||
|
||||
bool hasNext ();
|
||||
dw::core::ui::RadioButtonResource *getNext ();
|
||||
void unref ();
|
||||
};
|
||||
|
||||
lout::container::typed::List <FltkRadioButtonResource> *list;
|
||||
|
||||
protected:
|
||||
~Group ();
|
||||
|
||||
public:
|
||||
Group (FltkRadioButtonResource *radioButtonResource);
|
||||
|
||||
inline lout::container::typed::Iterator <FltkRadioButtonResource>
|
||||
iterator ()
|
||||
{
|
||||
return list->iterator ();
|
||||
}
|
||||
|
||||
inline dw::core::ui::RadioButtonResource::GroupIterator
|
||||
*groupIterator ()
|
||||
{
|
||||
return new FltkGroupIterator (list);
|
||||
}
|
||||
|
||||
void connect (FltkRadioButtonResource *radioButtonResource);
|
||||
void unconnect (FltkRadioButtonResource *radioButtonResource);
|
||||
};
|
||||
|
||||
Group *group;
|
||||
|
||||
static void widgetCallback (Fl_Widget *widget, void *data);
|
||||
void buttonClicked ();
|
||||
|
||||
protected:
|
||||
Fl_Button *createNewButton (core::Allocation *allocation);
|
||||
|
||||
public:
|
||||
FltkRadioButtonResource (FltkPlatform *platform,
|
||||
FltkRadioButtonResource *groupedWith,
|
||||
bool activated);
|
||||
~FltkRadioButtonResource ();
|
||||
|
||||
GroupIterator *groupIterator ();
|
||||
};
|
||||
|
||||
|
||||
template <class I> class FltkSelectionResource:
|
||||
public FltkSpecificResource <I>
|
||||
{
|
||||
protected:
|
||||
virtual bool setSelectedItems() { return false; }
|
||||
virtual void addItem (const char *str, bool enabled, bool selected) = 0;
|
||||
virtual void setItem (int index, bool selected) = 0;
|
||||
virtual void pushGroup (const char *name, bool enabled) = 0;
|
||||
virtual void popGroup () = 0;
|
||||
public:
|
||||
FltkSelectionResource (FltkPlatform *platform) :
|
||||
FltkSpecificResource<I> (platform) {};
|
||||
dw::core::Iterator *iterator (dw::core::Content::Type mask, bool atEnd);
|
||||
};
|
||||
|
||||
|
||||
class FltkOptionMenuResource:
|
||||
public FltkSelectionResource <dw::core::ui::OptionMenuResource>
|
||||
{
|
||||
protected:
|
||||
Fl_Widget *createNewWidget (core::Allocation *allocation);
|
||||
virtual bool setSelectedItems() { return true; }
|
||||
void setWidgetStyle (Fl_Widget *widget, core::style::Style *style);
|
||||
int getNumberOfItems();
|
||||
int getMaxItemWidth ();
|
||||
private:
|
||||
static void widgetCallback (Fl_Widget *widget, void *data);
|
||||
void enlargeMenu();
|
||||
Fl_Menu_Item *newItem();
|
||||
Fl_Menu_Item *menu;
|
||||
int itemsAllocated, itemsUsed;
|
||||
public:
|
||||
FltkOptionMenuResource (FltkPlatform *platform);
|
||||
~FltkOptionMenuResource ();
|
||||
|
||||
void addItem (const char *str, bool enabled, bool selected);
|
||||
void setItem (int index, bool selected);
|
||||
void pushGroup (const char *name, bool enabled);
|
||||
void popGroup ();
|
||||
|
||||
void sizeRequest (core::Requisition *requisition);
|
||||
bool isSelected (int index);
|
||||
};
|
||||
|
||||
class FltkListResource:
|
||||
public FltkSelectionResource <dw::core::ui::ListResource>
|
||||
{
|
||||
protected:
|
||||
Fl_Widget *createNewWidget (core::Allocation *allocation);
|
||||
void setWidgetStyle (Fl_Widget *widget, core::style::Style *style);
|
||||
int getNumberOfItems();
|
||||
int getMaxItemWidth ();
|
||||
private:
|
||||
static void widgetCallback (Fl_Widget *widget, void *data);
|
||||
void *newItem (const char *str, bool enabled, bool selected);
|
||||
int currDepth;
|
||||
int colWidths[4];
|
||||
int showRows;
|
||||
ListResource::SelectionMode mode;
|
||||
public:
|
||||
FltkListResource (FltkPlatform *platform,
|
||||
core::ui::ListResource::SelectionMode selectionMode,
|
||||
int rows);
|
||||
~FltkListResource ();
|
||||
|
||||
void addItem (const char *str, bool enabled, bool selected);
|
||||
void setItem (int index, bool selected);
|
||||
void pushGroup (const char *name, bool enabled);
|
||||
void popGroup ();
|
||||
|
||||
void sizeRequest (core::Requisition *requisition);
|
||||
bool isSelected (int index);
|
||||
};
|
||||
|
||||
|
||||
} // namespace ui
|
||||
} // namespace fltk
|
||||
} // namespace dw
|
||||
|
||||
|
||||
#endif // __DW_FLTK_UI_HH__
|
||||
Reference in New Issue
Block a user