713 lines
18 KiB
C++
713 lines
18 KiB
C++
/*
|
|
* Dillo Widget
|
|
*
|
|
* Copyright 2005-2007 Sebastian Geerken <sgeerken@dillo.org>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "dlib/dlib.hh"
|
|
#include "../lout/msg.h"
|
|
#include "../lout/debug.hh"
|
|
#include "fltkcore.hh"
|
|
|
|
#include <FL/fl_draw.H>
|
|
#include <FL/Fl_Box.H>
|
|
#include <FL/Fl_Tooltip.H>
|
|
#include <FL/Fl_Menu_Window.H>
|
|
#include <FL/Fl_Paged_Device.H>
|
|
|
|
/*
|
|
* Local data
|
|
*/
|
|
|
|
/* Tooltips */
|
|
static Fl_Menu_Window *tt_window = NULL;
|
|
static int in_tooltip = 0, req_tooltip = 0;
|
|
|
|
namespace dw {
|
|
namespace fltk {
|
|
|
|
using namespace lout;
|
|
|
|
/**
|
|
* \todo Distinction between italics and oblique would be nice.
|
|
*/
|
|
|
|
container::typed::HashTable <dw::core::style::FontAttrs,
|
|
FltkFont> *FltkFont::fontsTable =
|
|
new container::typed::HashTable <dw::core::style::FontAttrs,
|
|
FltkFont> (false, false);
|
|
|
|
std::optional< std::map< std::string, std::unique_ptr< FltkFont::FontFamily > > > FltkFont::systemFonts;
|
|
|
|
FltkFont::FontFamily FltkFont::standardFontFamily (FL_HELVETICA,
|
|
FL_HELVETICA_BOLD,
|
|
FL_HELVETICA_ITALIC,
|
|
FL_HELVETICA_BOLD_ITALIC);
|
|
|
|
FltkFont::FontFamily::FontFamily (Fl_Font fontNormal, Fl_Font fontBold,
|
|
Fl_Font fontItalic, Fl_Font fontBoldItalic)
|
|
{
|
|
font[0] = fontNormal;
|
|
font[1] = fontBold;
|
|
font[2] = fontItalic;
|
|
font[3] = fontBoldItalic;
|
|
}
|
|
|
|
void FltkFont::FontFamily::set (Fl_Font f, int attrs)
|
|
{
|
|
int idx = 0;
|
|
if (attrs & FL_BOLD)
|
|
idx += 1;
|
|
if (attrs & FL_ITALIC)
|
|
idx += 2;
|
|
font[idx] = f;
|
|
}
|
|
|
|
Fl_Font FltkFont::FontFamily::get (int attrs)
|
|
{
|
|
int idx = 0;
|
|
if (attrs & FL_BOLD)
|
|
idx += 1;
|
|
if (attrs & FL_ITALIC)
|
|
idx += 2;
|
|
|
|
// should the desired font style not exist, we
|
|
// return the normal font of the fontFamily
|
|
return font[idx] >= 0 ? font[idx] : font[0];
|
|
}
|
|
|
|
|
|
|
|
FltkFont::FltkFont (core::style::FontAttrs *attrs)
|
|
{
|
|
if (!systemFonts)
|
|
initSystemFonts ();
|
|
|
|
copyAttrs (attrs);
|
|
|
|
int fa = 0;
|
|
if (weight >= 500)
|
|
fa |= FL_BOLD;
|
|
if (style != core::style::FONT_STYLE_NORMAL)
|
|
fa |= FL_ITALIC;
|
|
|
|
FontFamily *family= nullptr;
|
|
if ( not systemFonts->contains( name ) )
|
|
family = &standardFontFamily;
|
|
else
|
|
family= systemFonts->at( name ).get();
|
|
assert( family );
|
|
|
|
font = family->get (fa);
|
|
|
|
fl_font(font, size);
|
|
// WORKAROUND: A bug with fl_width(uint_t) on non-xft X was present in
|
|
// 1.3.0 (STR #2688).
|
|
spaceWidth = std::max(0, (int)fl_width(" ") + letterSpacing);
|
|
int xx, xy, xw, xh;
|
|
fl_text_extents("x", xx, xy, xw, xh);
|
|
xHeight = xh;
|
|
zeroWidth = (int) fl_width("0");
|
|
descent = fl_descent();
|
|
ascent = fl_height() - descent;
|
|
}
|
|
|
|
FltkFont::~FltkFont ()
|
|
{
|
|
fontsTable->remove (this);
|
|
}
|
|
|
|
static void strstrip(char *big, const char *little)
|
|
{
|
|
if (strlen(big) >= strlen(little) &&
|
|
misc::AsciiStrcasecmp(big + strlen(big) - strlen(little), little) == 0)
|
|
*(big + strlen(big) - strlen(little)) = '\0';
|
|
}
|
|
|
|
void FltkFont::initSystemFonts ()
|
|
{
|
|
systemFonts.emplace();
|
|
|
|
int k = Fl::set_fonts ("-*-iso10646-1");
|
|
for (int i = 0; i < k; i++) {
|
|
int t;
|
|
std::string name = Fl::get_font_name ((Fl_Font) i, &t);
|
|
|
|
// normalize font family names (strip off "bold", "italic")
|
|
if (t & FL_ITALIC)
|
|
strstrip(name.data(), " italic");
|
|
if (t & FL_BOLD)
|
|
strstrip(name.data(), " bold");
|
|
|
|
_MSG("Found font: %s%s%s\n", name, t & FL_BOLD ? " bold" : "",
|
|
t & FL_ITALIC ? " italic" : "");
|
|
|
|
|
|
auto &family = (*systemFonts)[ name.c_str() ];
|
|
if( family ) {
|
|
family->set ((Fl_Font) i, t);
|
|
} else {
|
|
// set first font of family also as normal font in case there
|
|
// is no normal (non-bold, non-italic) font
|
|
family = std::make_unique< FontFamily >( (Fl_Font) i, -1, -1, -1 );
|
|
family->set( (Fl_Font) i, t );
|
|
}
|
|
}
|
|
}
|
|
|
|
bool
|
|
FltkFont::fontExists (const char *name)
|
|
{
|
|
if (!systemFonts)
|
|
initSystemFonts ();
|
|
return systemFonts->contains(name);
|
|
}
|
|
|
|
Fl_Font
|
|
FltkFont::get (const char *name, int attrs)
|
|
{
|
|
if (!systemFonts)
|
|
initSystemFonts ();
|
|
if( systemFonts->contains( name ) )
|
|
return systemFonts->at( name )->get (attrs);
|
|
else
|
|
return FL_HELVETICA;
|
|
}
|
|
|
|
bool
|
|
FltkPlatform::fontExists (const char *name)
|
|
{
|
|
return FltkFont::fontExists (name);
|
|
}
|
|
|
|
FltkFont*
|
|
FltkFont::create (core::style::FontAttrs *attrs)
|
|
{
|
|
FltkFont *font = fontsTable->get (attrs);
|
|
|
|
if (font == NULL) {
|
|
font = new FltkFont (attrs);
|
|
fontsTable->put (font, font);
|
|
}
|
|
|
|
return font;
|
|
}
|
|
|
|
container::typed::HashTable <dw::core::style::ColorAttrs,
|
|
FltkColor>
|
|
*FltkColor::colorsTable =
|
|
new container::typed::HashTable <dw::core::style::ColorAttrs,
|
|
FltkColor> (false, false);
|
|
|
|
FltkColor::FltkColor (int color): Color (color)
|
|
{
|
|
this->color = color;
|
|
|
|
if (!(colors[SHADING_NORMAL] = shadeColor (color, SHADING_NORMAL) << 8))
|
|
colors[SHADING_NORMAL] = FL_BLACK;
|
|
if (!(colors[SHADING_INVERSE] = shadeColor (color, SHADING_INVERSE) << 8))
|
|
colors[SHADING_INVERSE] = FL_BLACK;
|
|
if (!(colors[SHADING_DARK] = shadeColor (color, SHADING_DARK) << 8))
|
|
colors[SHADING_DARK] = FL_BLACK;
|
|
if (!(colors[SHADING_LIGHT] = shadeColor (color, SHADING_LIGHT) << 8))
|
|
colors[SHADING_LIGHT] = FL_BLACK;
|
|
}
|
|
|
|
FltkColor::~FltkColor ()
|
|
{
|
|
colorsTable->remove (this);
|
|
}
|
|
|
|
FltkColor * FltkColor::create (int col)
|
|
{
|
|
ColorAttrs attrs(col);
|
|
FltkColor *color = colorsTable->get (&attrs);
|
|
|
|
if (color == NULL) {
|
|
color = new FltkColor (col);
|
|
colorsTable->put (color, color);
|
|
}
|
|
|
|
return color;
|
|
}
|
|
|
|
FltkTooltip::FltkTooltip (const char *text) : Tooltip(text)
|
|
{
|
|
}
|
|
|
|
FltkTooltip::~FltkTooltip ()
|
|
{
|
|
if (in_tooltip || req_tooltip)
|
|
cancel(); /* cancel tooltip window */
|
|
}
|
|
|
|
FltkTooltip *FltkTooltip::create (const char *text)
|
|
{
|
|
return new FltkTooltip(text);
|
|
}
|
|
|
|
/*
|
|
* Tooltip callback: used to delay it a bit
|
|
* INVARIANT: Only one instance of this function is requested.
|
|
*/
|
|
static void tooltip_tcb(void *data)
|
|
{
|
|
req_tooltip = 2;
|
|
((FltkTooltip *)data)->onEnter();
|
|
req_tooltip = 0;
|
|
}
|
|
|
|
void FltkTooltip::onEnter()
|
|
{
|
|
_MSG("FltkTooltip::onEnter\n");
|
|
if (!str || !*str)
|
|
return;
|
|
if (req_tooltip == 0) {
|
|
Fl::remove_timeout(tooltip_tcb);
|
|
Fl::add_timeout(1.0, tooltip_tcb, this);
|
|
req_tooltip = 1;
|
|
return;
|
|
}
|
|
|
|
if (!tt_window) {
|
|
tt_window = new Fl_Menu_Window(0,0,100,24);
|
|
tt_window->set_override();
|
|
tt_window->box(FL_NO_BOX);
|
|
Fl_Box *b = new Fl_Box(0,0,100,24);
|
|
b->box(FL_BORDER_BOX);
|
|
b->color(fl_color_cube(FL_NUM_RED-1, FL_NUM_GREEN-1, FL_NUM_BLUE-2));
|
|
b->labelcolor(FL_BLACK);
|
|
b->labelfont(FL_HELVETICA);
|
|
b->labelsize(14);
|
|
b->align(FL_ALIGN_WRAP|FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
|
|
tt_window->resizable(b);
|
|
tt_window->end();
|
|
}
|
|
|
|
/* prepare tooltip window */
|
|
int x, y;
|
|
Fl_Box *box = (Fl_Box*)tt_window->child(0);
|
|
box->label(str);
|
|
Fl::get_mouse(x,y); y += 6;
|
|
/* calculate window size */
|
|
int ww, hh;
|
|
ww = 800; // max width;
|
|
box->measure_label(ww, hh);
|
|
ww += 6 + 2 * Fl::box_dx(box->box());
|
|
hh += 6 + 2 * Fl::box_dy(box->box());
|
|
tt_window->resize(x,y,ww,hh);
|
|
tt_window->show();
|
|
in_tooltip = 1;
|
|
}
|
|
|
|
/*
|
|
* Leaving the widget cancels the tooltip
|
|
*/
|
|
void FltkTooltip::onLeave()
|
|
{
|
|
_MSG(" FltkTooltip::onLeave in_tooltip=%d\n", in_tooltip);
|
|
cancel();
|
|
}
|
|
|
|
void FltkPlatform::cancelTooltip()
|
|
{
|
|
FltkTooltip::cancel();
|
|
}
|
|
|
|
/*
|
|
* Remove a shown tooltip or cancel a pending one
|
|
*/
|
|
void FltkTooltip::cancel()
|
|
{
|
|
if (req_tooltip) {
|
|
Fl::remove_timeout(tooltip_tcb);
|
|
req_tooltip = 0;
|
|
}
|
|
if (!in_tooltip) return;
|
|
in_tooltip = 0;
|
|
tt_window->hide();
|
|
|
|
/* WORKAROUND: (Black magic here)
|
|
* Hiding a tooltip with the keyboard or mousewheel doesn't work.
|
|
* The code below "fixes" the problem */
|
|
Fl_Widget *widget = Fl::belowmouse();
|
|
if (widget && widget->window()) {
|
|
widget->window()->damage(FL_DAMAGE_EXPOSE,0,0,1,1);
|
|
}
|
|
}
|
|
|
|
void FltkTooltip::onMotion()
|
|
{
|
|
}
|
|
|
|
void FltkView::addFltkWidget (Fl_Widget *widget,
|
|
core::Allocation *allocation)
|
|
{
|
|
}
|
|
|
|
void FltkView::removeFltkWidget (Fl_Widget *widget)
|
|
{
|
|
}
|
|
|
|
void FltkView::allocateFltkWidget (Fl_Widget *widget,
|
|
core::Allocation *allocation)
|
|
{
|
|
}
|
|
|
|
void FltkView::drawFltkWidget (Fl_Widget *widget, core::Rectangle *area)
|
|
{
|
|
}
|
|
|
|
|
|
core::ui::LabelButtonResource *
|
|
FltkPlatform::FltkResourceFactory::createLabelButtonResource (const char
|
|
*label)
|
|
{
|
|
return new ui::FltkLabelButtonResource (platform, label);
|
|
}
|
|
|
|
core::ui::ComplexButtonResource *
|
|
FltkPlatform::FltkResourceFactory::createComplexButtonResource (std::unique_ptr< core::Widget > widget,
|
|
bool relief)
|
|
{
|
|
return new ui::FltkComplexButtonResource (platform, std::move( widget ), relief);
|
|
}
|
|
|
|
core::ui::ListResource *
|
|
FltkPlatform::FltkResourceFactory::createListResource (core::ui
|
|
::ListResource
|
|
::SelectionMode
|
|
selectionMode, int rows)
|
|
{
|
|
return new ui::FltkListResource (platform, selectionMode, rows);
|
|
}
|
|
|
|
core::ui::OptionMenuResource *
|
|
FltkPlatform::FltkResourceFactory::createOptionMenuResource ()
|
|
{
|
|
return new ui::FltkOptionMenuResource (platform);
|
|
}
|
|
|
|
core::ui::EntryResource *
|
|
FltkPlatform::FltkResourceFactory::createEntryResource (int size,
|
|
bool password,
|
|
const char *label,
|
|
const char *placeholder)
|
|
{
|
|
return new ui::FltkEntryResource (platform, size, password, label,
|
|
placeholder);
|
|
}
|
|
|
|
core::ui::MultiLineTextResource *
|
|
FltkPlatform::FltkResourceFactory::createMultiLineTextResource (int cols,
|
|
int rows,
|
|
const char *placeholder)
|
|
{
|
|
return new ui::FltkMultiLineTextResource (platform, cols, rows,placeholder);
|
|
}
|
|
|
|
core::ui::CheckButtonResource *
|
|
FltkPlatform::FltkResourceFactory::createCheckButtonResource (bool activated)
|
|
{
|
|
return new ui::FltkCheckButtonResource (platform, activated);
|
|
}
|
|
|
|
core::ui::RadioButtonResource
|
|
*FltkPlatform::FltkResourceFactory::createRadioButtonResource
|
|
(core::ui::RadioButtonResource *groupedWith, bool activated)
|
|
{
|
|
return
|
|
new ui::FltkRadioButtonResource (platform,
|
|
(ui::FltkRadioButtonResource*)
|
|
groupedWith,
|
|
activated);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
FltkPlatform::FltkPlatform ()
|
|
{
|
|
DBG_OBJ_CREATE ("dw::fltk::FltkPlatform");
|
|
|
|
layout = NULL;
|
|
idleFuncRunning = false;
|
|
idleFuncId = 0;
|
|
|
|
view = NULL;
|
|
resources = new container::typed::List <ui::FltkResource> (false);
|
|
|
|
resourceFactory.setPlatform (this);
|
|
}
|
|
|
|
FltkPlatform::~FltkPlatform ()
|
|
{
|
|
if (idleFuncRunning)
|
|
Fl::remove_idle (generalStaticIdle, (void*)this);
|
|
delete resources;
|
|
|
|
DBG_OBJ_DELETE ();
|
|
}
|
|
|
|
void FltkPlatform::setLayout (core::Layout *layout)
|
|
{
|
|
this->layout = layout;
|
|
DBG_OBJ_ASSOC_CHILD (layout);
|
|
}
|
|
|
|
|
|
void FltkPlatform::attachView (core::View *view)
|
|
{
|
|
if (this->view)
|
|
MSG_ERR("FltkPlatform::attachView: multiple views!\n");
|
|
this->view = (FltkView*)view;
|
|
|
|
for (container::typed::Iterator <ui::FltkResource> it =
|
|
resources->iterator (); it.hasNext (); ) {
|
|
ui::FltkResource *resource = it.getNext ();
|
|
resource->attachView (this->view);
|
|
}
|
|
}
|
|
|
|
|
|
void FltkPlatform::detachView (core::View *view)
|
|
{
|
|
if (this->view != view)
|
|
MSG_ERR("FltkPlatform::detachView: this->view: %p view: %p\n",
|
|
(void *) this->view, (void *) view);
|
|
|
|
for (container::typed::Iterator <ui::FltkResource> it =
|
|
resources->iterator (); it.hasNext (); ) {
|
|
ui::FltkResource *resource = it.getNext ();
|
|
resource->detachView ((FltkView*)view);
|
|
}
|
|
this->view = NULL;
|
|
}
|
|
|
|
|
|
int FltkPlatform::textWidth (core::style::Font *font, const char *text,
|
|
int len)
|
|
{
|
|
char chbuf[4];
|
|
int c, cu;
|
|
int width = 0;
|
|
FltkFont *ff = (FltkFont*) font;
|
|
int curr = 0, next = 0, nb;
|
|
|
|
if (font->fontVariant == core::style::FONT_VARIANT_SMALL_CAPS) {
|
|
int sc_fontsize = lout::misc::roundInt(ff->size * 0.78);
|
|
for (curr = 0; next < len; curr = next) {
|
|
next = nextGlyph(text, curr);
|
|
c = fl_utf8decode(text + curr, text + next, &nb);
|
|
if ((cu = fl_toupper(c)) == c) {
|
|
/* already uppercase, just draw the character */
|
|
fl_font(ff->font, ff->size);
|
|
if (fl_nonspacing(cu) == 0) {
|
|
width += font->letterSpacing;
|
|
width += (int)fl_width(text + curr, next - curr);
|
|
}
|
|
} else {
|
|
/* make utf8 string for converted char */
|
|
nb = fl_utf8encode(cu, chbuf);
|
|
fl_font(ff->font, sc_fontsize);
|
|
if (fl_nonspacing(cu) == 0) {
|
|
width += font->letterSpacing;
|
|
width += (int)fl_width(chbuf, nb);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
fl_font (ff->font, ff->size);
|
|
width = (int) fl_width (text, len);
|
|
|
|
if (font->letterSpacing) {
|
|
int curr = 0, next = 0;
|
|
|
|
while (next < len) {
|
|
next = nextGlyph(text, curr);
|
|
c = fl_utf8decode(text + curr, text + next, &nb);
|
|
if (fl_nonspacing(c) == 0)
|
|
width += font->letterSpacing;
|
|
curr = next;
|
|
}
|
|
}
|
|
}
|
|
|
|
return width;
|
|
}
|
|
|
|
char *FltkPlatform::textToUpper (const char *text, int len)
|
|
{
|
|
char *newstr = NULL;
|
|
|
|
if (len > 0) {
|
|
int newlen;
|
|
|
|
newstr = (char*) malloc(3 * len + 1);
|
|
newlen = fl_utf_toupper((const unsigned char*)text, len, newstr);
|
|
assert(newlen <= 3 * len);
|
|
newstr[newlen] = '\0';
|
|
}
|
|
return newstr;
|
|
}
|
|
|
|
char *FltkPlatform::textToLower (const char *text, int len)
|
|
{
|
|
char *newstr = NULL;
|
|
|
|
if (len > 0) {
|
|
int newlen;
|
|
|
|
newstr = (char*) malloc(3 * len + 1);
|
|
newlen = fl_utf_tolower((const unsigned char*)text, len, newstr);
|
|
assert(newlen <= 3 * len);
|
|
newstr[newlen] = '\0';
|
|
}
|
|
return newstr;
|
|
}
|
|
|
|
int FltkPlatform::nextGlyph (const char *text, int idx)
|
|
{
|
|
return fl_utf8fwd (&text[idx + 1], text, &text[strlen (text)]) - text;
|
|
}
|
|
|
|
int FltkPlatform::prevGlyph (const char *text, int idx)
|
|
{
|
|
return fl_utf8back (&text[idx - 1], text, &text[strlen (text)]) - text;
|
|
}
|
|
|
|
float FltkPlatform::dpiX ()
|
|
{
|
|
float horizontal, vertical;
|
|
|
|
Fl::screen_dpi(horizontal, vertical);
|
|
return horizontal;
|
|
}
|
|
|
|
float FltkPlatform::dpiY ()
|
|
{
|
|
float horizontal, vertical;
|
|
|
|
Fl::screen_dpi(horizontal, vertical);
|
|
return vertical;
|
|
}
|
|
|
|
void FltkPlatform::generalStaticIdle (void *data)
|
|
{
|
|
((FltkPlatform*)data)->generalIdle();
|
|
}
|
|
|
|
void FltkPlatform::generalIdle ()
|
|
{
|
|
if (!idleQueue.empty ()) {
|
|
/* Execute the first function in the list. */
|
|
auto &idleFunc = idleQueue.front();
|
|
(layout->*(idleFunc->func)) ();
|
|
|
|
/* Remove this function. */
|
|
idleQueue.remove(idleFunc);
|
|
}
|
|
|
|
if (idleQueue.empty()) {
|
|
idleFuncRunning = false;
|
|
Fl::remove_idle (generalStaticIdle, (void*)this);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* \todo Incomplete comments.
|
|
*/
|
|
int FltkPlatform::addIdle (void (core::Layout::*func) ())
|
|
{
|
|
/*
|
|
* Since ... (todo) we have to wrap around fltk_add_idle. There is only one
|
|
* idle function, the passed idle function is put into a queue.
|
|
*/
|
|
if (!idleFuncRunning) {
|
|
Fl::add_idle (generalStaticIdle, (void*)this);
|
|
idleFuncRunning = true;
|
|
}
|
|
|
|
idleFuncId++;
|
|
|
|
auto idleFunc = std::make_unique< IdleFunc >();
|
|
idleFunc->id = idleFuncId;
|
|
idleFunc->func = func;
|
|
idleQueue.push_back( std::move( idleFunc ) );
|
|
|
|
return idleFuncId;
|
|
}
|
|
|
|
void FltkPlatform::removeIdle (int idleId)
|
|
{
|
|
const auto found= std::find_if( begin( idleQueue ), end( idleQueue ),
|
|
[&]( const auto &idleFunc ) { return idleFunc->id == idleId; } );
|
|
if( found != end( idleQueue ) ) idleQueue.erase( found );
|
|
|
|
if (idleFuncRunning && idleQueue.empty())
|
|
Fl::remove_idle (generalStaticIdle, (void*)this);
|
|
}
|
|
|
|
core::style::Font *FltkPlatform::createFont (core::style::FontAttrs
|
|
*attrs,
|
|
bool tryEverything)
|
|
{
|
|
return FltkFont::create (attrs);
|
|
}
|
|
|
|
core::style::Color *FltkPlatform::createColor (int color)
|
|
{
|
|
return FltkColor::create (color);
|
|
}
|
|
|
|
core::style::Tooltip *FltkPlatform::createTooltip (const char *text)
|
|
{
|
|
return FltkTooltip::create (text);
|
|
}
|
|
|
|
void FltkPlatform::copySelection(const char *text)
|
|
{
|
|
Fl::copy(text, strlen(text), 0);
|
|
}
|
|
|
|
std::unique_ptr< core::Imgbuf >
|
|
FltkPlatform::createImgbuf( core::Imgbuf::Type type,
|
|
int width, int height, double gamma)
|
|
{
|
|
return std::make_unique< FltkImgbuf >( type, width, height, gamma );
|
|
}
|
|
|
|
core::ui::ResourceFactory *FltkPlatform::getResourceFactory ()
|
|
{
|
|
return &resourceFactory;
|
|
}
|
|
|
|
|
|
void FltkPlatform::attachResource (ui::FltkResource *resource)
|
|
{
|
|
resources->append (resource);
|
|
resource->attachView (view);
|
|
}
|
|
|
|
void FltkPlatform::detachResource (ui::FltkResource *resource)
|
|
{
|
|
resources->removeRef (resource);
|
|
}
|
|
|
|
} // namespace fltk
|
|
} // namespace dw
|