From: Angus Leeming Date: Wed, 2 Apr 2003 14:20:30 +0000 (+0000) Subject: The new combox code. X-Git-Tag: 1.6.10~17081 X-Git-Url: https://git.lyx.org/gitweb/?a=commitdiff_plain;h=9bfcf348c803464b285237ebdb012586fae79c6e;p=features.git The new combox code. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@6681 a592a061-630c-0410-9148-cb99ea01b6c8 --- diff --git a/src/frontends/xforms/ChangeLog b/src/frontends/xforms/ChangeLog index 3d1f8824c0..07515142a4 100644 --- a/src/frontends/xforms/ChangeLog +++ b/src/frontends/xforms/ChangeLog @@ -2,6 +2,36 @@ * forms/form_character.fd: rearrange widget order. +2003-04-02 Angus Leeming + + * combox.C: + * DropDown.[Ch]: removed. + + * combox.[ch]: + * freebrowser.[ch]: replace Alejandro's Combox and John's DropDown + C++ code with something that can be integrated into xforms itself. + + * Dialogs2.C: remove #include "combox.h". + + * FormCharacter.[Ch]: + * forms/form_character.fd: + * FormDocument.[Ch]: + * forms/form_document.fd: + * FormPreferences.[Ch]: + * forms/form_preferences.fd: + * Toolbar_pimpl.[Ch]: replace code using Alejandro's Combox with + code using an FL_OBJECT of type FL_COMBOX. + + * XMiniBuffer.[Ch]: replace John's DropDown with code using + FL_FREEBROWSER. + + * Makefile.am: remove combox.C, DropDown.[Ch]. + Add combox.c, freebrowser.[ch]. + + * forms/README: + * forms/fdfix.sh: + * forms/fdfixc.sed: update to suit the new combox code. + 2003-04-02 Angus Leeming * FormDocument.[Ch]: diff --git a/src/frontends/xforms/Dialogs2.C b/src/frontends/xforms/Dialogs2.C index ae61936131..0c95fde981 100644 --- a/src/frontends/xforms/Dialogs2.C +++ b/src/frontends/xforms/Dialogs2.C @@ -18,7 +18,6 @@ #include "Tooltips.h" #include "xformsBC.h" -#include "combox.h" #include "ControlDocument.h" #include "FormDocument.h" diff --git a/src/frontends/xforms/DropDown.C b/src/frontends/xforms/DropDown.C deleted file mode 100644 index edbc83a7e7..0000000000 --- a/src/frontends/xforms/DropDown.C +++ /dev/null @@ -1,188 +0,0 @@ -/** - * \file DropDown.C - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author John Levon - * - * Full author contact details are available in file CREDITS - */ - -#include - - -#include "DropDown.h" -#include "xforms_helpers.h" - -#include FORMS_H_LOCATION - -#include -#include - -#ifndef CXX_GLOBAL_CSTD -using std::isprint; -#endif - -using std::vector; - - -namespace { - -extern "C" void C_CompletedCB(FL_OBJECT * ob, long) -{ - DropDown * d = static_cast(ob->u_vdata); - d->completed(); -} - - -extern "C" int C_PeekCB(FL_FORM * form, void *xev) -{ - DropDown * d = static_cast(form->u_vdata); - return d->peek(static_cast(xev)); -} - -} // namespace anon - - -DropDown::DropDown(FL_OBJECT * ob) -{ - form_ = fl_bgn_form(FL_NO_BOX, ob->w, 100); - fl_add_box(FL_UP_BOX, 0, 0, ob->w, 100, ""); - browser_ = fl_add_browser(FL_SELECT_BROWSER, 0, 0, ob->w, 100, ""); - form_->u_vdata = this; - browser_->u_vdata = this; - fl_set_object_callback(browser_, C_CompletedCB, 0); - fl_register_raw_callback(form_, KeyPressMask|ButtonPressMask, C_PeekCB); - fl_end_form(); -} - - -DropDown::~DropDown() -{ - if (form_->visible) - fl_hide_form(form_); - fl_free_form(form_); -} - - -void DropDown::select(vector const & choices, int x, int y, int w) -{ - if (choices.empty()) - return; - - fl_set_form_geometry(form_, x, y - 100, w, 100); - fl_clear_browser(browser_); - - vector::const_iterator cit = choices.begin(); - vector::const_iterator end = choices.end(); - for (; cit != end; ++cit) { - fl_add_browser_line(browser_, cit->c_str()); - } - fl_select_browser_line(browser_, 1); - fl_show_form(form_, FL_PLACE_POSITION, FL_NOBORDER, ""); - XGrabPointer(fl_get_display(), form_->window, false, - ButtonPressMask | ButtonReleaseMask | PointerMotionMask, - GrabModeAsync, GrabModeAsync, 0, 0, 0); - XFlush(fl_get_display()); -} - - -void DropDown::line_up() -{ - if (fl_get_browser(browser_) > 1) - fl_select_browser_line(browser_, fl_get_browser(browser_) - 1); - if (fl_get_browser(browser_) >= fl_get_browser_topline(browser_) + - fl_get_browser_screenlines(browser_)) - fl_set_browser_topline(browser_, fl_get_browser(browser_) - - fl_get_browser_screenlines(browser_) + 1); - if (fl_get_browser(browser_) < fl_get_browser_topline(browser_)) - fl_set_browser_topline(browser_, fl_get_browser(browser_)); -} - - -void DropDown::line_down() -{ - if (fl_get_browser(browser_) < fl_get_browser_maxline(browser_)) - fl_select_browser_line(browser_, fl_get_browser(browser_) + 1); - if (fl_get_browser(browser_) >= fl_get_browser_topline(browser_) + - fl_get_browser_screenlines(browser_)) - fl_set_browser_topline(browser_, fl_get_browser(browser_) - - fl_get_browser_screenlines(browser_) + 1); - if (fl_get_browser(browser_) < fl_get_browser_topline(browser_)) - fl_set_browser_topline(browser_, fl_get_browser(browser_)); -} - - -int DropDown::peek(XEvent * xev) -{ - int x,y; - unsigned int keymask; - - fl_get_mouse(&x, &y, &keymask); - - if (xev->type == ButtonPress) { - if (!(x >= form_->x && x <= (form_->x + form_->w) && - y >= form_->y && y << (form_->y + form_->h))) { - fl_hide_form(form_); - return 1; - } - XUngrabPointer(fl_get_display(), CurrentTime); - } else if (xev->type == KeyPress) { - char s_r[10]; s_r[9] = '\0'; - KeySym keysym_return; - XLookupString(&xev->xkey, s_r, 10, &keysym_return, 0); - switch (keysym_return) { - case XK_Down: -#ifdef XK_KP_Down - case XK_KP_Down: -#endif - line_down(); - return 1; - case XK_Up: -#ifdef XK_KP_Up - case XK_KP_Up: -#endif - line_up(); - return 1; - case XK_Return: -#ifdef XK_KP_Enter - case XK_KP_Enter: -#endif - completed(); - return 1; - case XK_Escape: - fl_deselect_browser(browser_); - completed(); - return 1; - default: - // FIXME: if someone has a got a way to - // convince the event to fall back to the - // minibuffer, I'm glad to hear it. - // fl_XPutBackEvent() doesn't work. - - // This is a bit less elegant perhaps, but works - // well enough. Angus 11 Jan 2002 - if (s_r[0] && isprint(s_r[0])) { - key_pressed(s_r[0]); - return 1; - } - } - } - return 0; -} - - -void DropDown::completed() -{ - XUngrabPointer(fl_get_display(), CurrentTime); - fl_hide_form(form_); - result(getString(browser_)); -} - - -void DropDown::key_pressed(char c) -{ - XUngrabPointer(fl_get_display(), CurrentTime); - fl_hide_form(form_); - keypress(c); -} diff --git a/src/frontends/xforms/DropDown.h b/src/frontends/xforms/DropDown.h deleted file mode 100644 index 317301b5b5..0000000000 --- a/src/frontends/xforms/DropDown.h +++ /dev/null @@ -1,63 +0,0 @@ -// -*- C++ -*- -/** - * \file DropDown.h - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author John Levon - * - * Full author contact details are available in file CREDITS - */ - -#ifndef DROPDOWN_H -#define DROPDOWN_H - - -#include "forms_fwd.h" -#include - -#include - -#include "LString.h" -#include - -class DropDown { -public: - /// constructor - DropDown(FL_OBJECT * ob); - /// destructor - ~DropDown(); - - /// choose from the list of choices. - void select(std::vector const & choices, int x, int y, int w); - - /// user completed action - void completed(); - - /// a key was pressed. Act on it. - void key_pressed(char c); - - /// signal for completion - boost::signal1 result; - - /// signal that a key was pressed - boost::signal1 keypress; - - /// X event - int peek(XEvent *); - -private: - /// move up a browser line - void line_up(); - - /// move down a browser line - void line_down(); - - /// our form - FL_FORM * form_; - - /// the browser - FL_OBJECT * browser_; -}; - -#endif // DROPDOWN_H diff --git a/src/frontends/xforms/FormCharacter.C b/src/frontends/xforms/FormCharacter.C index d4ba682f13..f20ec08aca 100644 --- a/src/frontends/xforms/FormCharacter.C +++ b/src/frontends/xforms/FormCharacter.C @@ -20,10 +20,10 @@ #include "FormCharacter.h" #include "forms/form_character.h" #include "gettext.h" -#include "combox.h" #include "helper_funcs.h" #include "xforms_helpers.h" #include FORMS_H_LOCATION +#include "combox.h" #include "frnt_lang.h" @@ -41,14 +41,6 @@ FormCharacter::FormCharacter(Dialog & parent) {} -void FormCharacter::ComboInputCB(int, void * v, Combox *) -{ - FormCharacter * pre = static_cast(v); - // must use input() directly, to avoid treating the Combox - // as an FL_OBJECT, leading to a crash (bug 406) - pre->bc().input(pre->input(0, 0)); -} - void FormCharacter::build() { dialog_.reset(build_character(this)); @@ -90,27 +82,9 @@ void FormCharacter::build() choice = ' ' + getStringFromVector(getFirst(color), " | ") + ' '; fl_addto_choice(dialog_->choice_color, choice.c_str()); - // xforms appears to need this to prevent a crash... - fl_addto_choice(dialog_->choice_language, "prevent crash"); - - // insert default language box manually - fl_addto_form(dialog_->form); - FL_OBJECT * ob = dialog_->choice_language; - fl_hide_object(dialog_->choice_language); - - combo_language2_.reset(new Combox(FL_COMBOX_DROPLIST)); - combo_language2_->add(ob->x, ob->y, ob->w, ob->h, 250); - combo_language2_->shortcut("#L", 1); - combo_language2_->setcallback(ComboInputCB, this); - fl_end_form(); - - // build up the combox entries - vector::const_iterator it = langs.begin(); - vector::const_iterator end = langs.end(); - for (; it != end; ++it) { - combo_language2_->addto(it->first); - } - combo_language2_->select(1); + choice = ' ' + getStringFromVector(getFirst(langs), " | ") + ' '; + fl_addto_combox(dialog_->combox_language, choice.c_str()); + fl_set_combox_browser_height(dialog_->combox_language, 250); // Manage the ok, apply and cancel/close buttons bcview().setApply(dialog_->button_apply); @@ -141,7 +115,7 @@ void FormCharacter::apply() pos = fl_get_choice(dialog_->choice_color); controller().setColor(color_[pos - 1]); - pos = combo_language2_->get(); + pos = fl_get_combox(dialog_->combox_language); controller().setLanguage(lang_[pos - 1]); bool const toggleall = fl_get_button(dialog_->check_toggle_all); @@ -170,7 +144,7 @@ void FormCharacter::update() fl_set_choice(dialog_->choice_color, pos+1); pos = int(findPos(lang_, controller().getLanguage())); - combo_language2_->select(pos+1); + fl_set_combox(dialog_->combox_language, pos+1); fl_set_button(dialog_->check_toggle_all, controller().getToggleAll()); } @@ -204,7 +178,7 @@ ButtonPolicy::SMInput FormCharacter::input(FL_OBJECT *, long) if (color_[pos - 1] != LColor::ignore) activate = ButtonPolicy::SMI_VALID; - pos = combo_language2_->get(); + pos = fl_get_combox(dialog_->combox_language); if (lang_[pos - 1] != "No change") activate = ButtonPolicy::SMI_VALID; diff --git a/src/frontends/xforms/FormCharacter.h b/src/frontends/xforms/FormCharacter.h index 42e987bb7b..c70c0b7c1b 100644 --- a/src/frontends/xforms/FormCharacter.h +++ b/src/frontends/xforms/FormCharacter.h @@ -20,9 +20,6 @@ #include "LColor.h" // for LColor enum #include "character.h" // for FONT_STATE enum -#include - -class Combox; struct FD_character; /** @@ -49,12 +46,6 @@ private: /// Filter the inputs on callback from xforms virtual ButtonPolicy::SMInput input(FL_OBJECT *, long); - /** Callback method (used only to activate Apply button when - combox is changed */ - static void ComboInputCB(int, void *, Combox *); - - /// - boost::scoped_ptr combo_language2_; /// std::vector family_; /// diff --git a/src/frontends/xforms/FormDocument.C b/src/frontends/xforms/FormDocument.C index fd9c18ff3b..3a6057fb14 100644 --- a/src/frontends/xforms/FormDocument.C +++ b/src/frontends/xforms/FormDocument.C @@ -20,7 +20,6 @@ #include "bmtable.h" #include "checkedwidgets.h" -#include "combox.h" #include "input_validators.h" // fl_unsigned_float_filter #include "xforms_helpers.h" @@ -39,6 +38,7 @@ #include XPM_H_LOCATION #include FORMS_H_LOCATION +#include "combox.h" #include @@ -88,6 +88,7 @@ void FormDocument::build() class_.reset(build_document_class(this)); // disable for read-only documents + bcview().addReadOnly(class_->combox_doc_class); bcview().addReadOnly(class_->radio_doc_indent); bcview().addReadOnly(class_->radio_doc_skip); bcview().addReadOnly(class_->choice_doc_pagestyle); @@ -118,19 +119,14 @@ void FormDocument::build() FL_OBJECT * obj; - // the class list is a combo-box and has to be inserted manually - obj = class_->choice_doc_class; - fl_deactivate_object(obj); - fl_addto_form(class_->form); - combo_doc_class.reset(new Combox(FL_COMBOX_DROPLIST)); - combo_doc_class->add(obj->x, obj->y, obj->w, obj->h, 400); - combo_doc_class->shortcut("#C",1); - combo_doc_class->setcallback(ComboInputCB, this); - fl_end_form(); - for (LyXTextClassList::const_iterator cit = textclasslist.begin(); - cit != textclasslist.end(); ++cit) { - combo_doc_class->addto(cit->description()); + // Fill the combox and choices. + obj = class_->combox_doc_class; + LyXTextClassList::const_iterator tit = textclasslist.begin(); + LyXTextClassList::const_iterator tend = textclasslist.end(); + for (; tit != tend; ++tit) { + fl_addto_combox(obj, tit->description().c_str()); } + fl_set_combox_browser_height(obj, 400); fl_addto_choice(class_->choice_doc_spacing, _(" Single | OneHalf | Double | Custom ")); @@ -239,6 +235,7 @@ void FormDocument::build() language_.reset(build_document_language(this)); // disable for read-only documents + bcview().addReadOnly(language_->combox_language); bcview().addReadOnly(language_->choice_inputenc); bcview().addReadOnly(language_->choice_quotes_language); bcview().addReadOnly(language_->radio_single); @@ -252,22 +249,13 @@ void FormDocument::build() // Store the identifiers for later lang_ = getSecond(langs); - // The language is a combo-box and has to be inserted manually - obj = language_->choice_language; - fl_deactivate_object(obj); - fl_addto_form(language_->form); - combo_language.reset(new Combox(FL_COMBOX_DROPLIST)); - combo_language->add(obj->x, obj->y, obj->w, obj->h, 400); - combo_language->shortcut("#L",1); - combo_language->setcallback(ComboInputCB, this); - fl_end_form(); - vector::const_iterator lit = langs.begin(); vector::const_iterator lend = langs.end(); for (; lit != lend; ++lit) { - combo_language->addto(lit->first); + fl_addto_combox(language_->combox_language, + lit->first.c_str()); } - combo_language->select(1); + fl_set_combox_browser_height(language_->combox_language, 400); fl_addto_choice(language_->choice_quotes_language, _(" ``text'' | ''text'' | ,,text`` | ,,text'' |" @@ -416,6 +404,8 @@ ButtonPolicy::SMInput FormDocument::input(FL_OBJECT * ob, long) setEnabled(class_->input_doc_spacing, fl_get_choice(class_->choice_doc_spacing) == 4); + } else if (ob == class_->combox_doc_class) { + CheckChoiceClass(); } else if (ob == class_->radio_doc_skip || ob == class_->radio_doc_indent || ob == class_->choice_doc_skip) { @@ -449,7 +439,7 @@ ButtonPolicy::SMInput FormDocument::input(FL_OBJECT * ob, long) } else if (ob == dialog_->button_reset_defaults) { BufferParams & params = controller().params(); - params.textclass = combo_doc_class->get() - 1; + params.textclass = fl_get_combox(class_->combox_doc_class) - 1; params.useClassDefaults(); UpdateLayoutDocument(params); @@ -593,15 +583,6 @@ ButtonPolicy::SMInput FormDocument::input(FL_OBJECT * ob, long) } -void FormDocument::ComboInputCB(int, void * v, Combox * combox) -{ - FormDocument * pre = static_cast(v); - if (combox == pre->combo_doc_class.get()) - pre->CheckChoiceClass(); - pre->bc().valid(); -} - - bool FormDocument::class_apply(BufferParams ¶ms) { bool redo = false; @@ -616,7 +597,7 @@ bool FormDocument::class_apply(BufferParams ¶ms) params.fontsize = getString(class_->choice_doc_fontsize); params.pagestyle = getString(class_->choice_doc_pagestyle); - params.textclass = combo_doc_class->get() - 1; + params.textclass = fl_get_combox(class_->combox_doc_class) - 1; BufferParams::PARSEP tmpsep = params.paragraph_separation; if (fl_get_button(class_->radio_doc_indent)) @@ -778,7 +759,7 @@ bool FormDocument::language_apply(BufferParams & params) else params.quotes_times = InsetQuotes::DoubleQ; - int const pos = combo_language->get(); + int const pos = fl_get_combox(language_->combox_language); Language const * new_language = languages.getLanguage(lang_[pos-1]); if (!new_language) new_language = default_language; @@ -820,11 +801,9 @@ void FormDocument::bullets_apply(BufferParams & params) /* update the bullet settings */ BufferParams & buf_params = controller().params(); - // a little bit of loop unrolling - params.user_defined_bullets[0] = buf_params.temp_bullets[0]; - params.user_defined_bullets[1] = buf_params.temp_bullets[1]; - params.user_defined_bullets[2] = buf_params.temp_bullets[2]; - params.user_defined_bullets[3] = buf_params.temp_bullets[3]; + for (int i = 0; i < 4; ++i) { + params.user_defined_bullets[i] = buf_params.temp_bullets[i]; + } } @@ -835,7 +814,7 @@ void FormDocument::UpdateClassParams(BufferParams const & params) LyXTextClass const & tclass = textclasslist[params.textclass]; - combo_doc_class->select(tclass.description()); + fl_set_combox(class_->combox_doc_class, params.textclass + 1); fl_clear_choice(class_->choice_doc_fontsize); fl_addto_choice(class_->choice_doc_fontsize, "default"); fl_addto_choice(class_->choice_doc_fontsize, @@ -945,7 +924,7 @@ void FormDocument::language_update(BufferParams const & params) return; int const pos = int(findPos(lang_, params.language->lang())); - combo_language->select(pos+1); + fl_set_combox(language_->combox_language, pos+1); fl_set_choice_text(language_->choice_inputenc, params.inputenc.c_str()); fl_set_choice(language_->choice_quotes_language, params.quotes_language + 1); @@ -1095,13 +1074,9 @@ void FormDocument::bullets_update(BufferParams const & params) void FormDocument::checkReadOnly() { if (bc().readOnly(controller().bufferIsReadonly())) { - combo_doc_class->deactivate(); - combo_language->deactivate(); postWarning(_("Document is read-only." " No changes to layout permitted.")); } else { - combo_doc_class->activate(); - combo_language->activate(); clearMessage(); } } @@ -1238,7 +1213,8 @@ void FormDocument::CheckChoiceClass() { BufferParams & params = controller().params(); - lyx::textclass_type const tc = combo_doc_class->get() - 1; + lyx::textclass_type const tc = + fl_get_combox(class_->combox_doc_class) - 1; if (controller().loadTextclass(tc)) { params.textclass = tc; @@ -1254,7 +1230,7 @@ void FormDocument::CheckChoiceClass() } else { int const revert = int(params.textclass); - combo_doc_class->select(revert + 1); + fl_set_combox(class_->combox_doc_class, revert + 1); } } diff --git a/src/frontends/xforms/FormDocument.h b/src/frontends/xforms/FormDocument.h index ad3a5a3406..41d5686e24 100644 --- a/src/frontends/xforms/FormDocument.h +++ b/src/frontends/xforms/FormDocument.h @@ -21,7 +21,6 @@ class ControlDocument; -class Combox; class BufferParams; struct FD_document; @@ -37,8 +36,6 @@ struct FD_document_bullet; class FormDocument : public FormCB > { public: FormDocument(); - /// - static void ComboInputCB(int, void *, Combox *); private: /** Redraw the form (on receipt of a Signal indicating, for example, that the xforms colours have been re-mapped). */ @@ -114,10 +111,6 @@ private: /// FL_OBJECT * fbullet; /// - boost::scoped_ptr combo_language; - /// - boost::scoped_ptr combo_doc_class; - /// std::vector lang_; }; diff --git a/src/frontends/xforms/FormPreferences.C b/src/frontends/xforms/FormPreferences.C index 7b2634586e..967d2acd60 100644 --- a/src/frontends/xforms/FormPreferences.C +++ b/src/frontends/xforms/FormPreferences.C @@ -17,7 +17,6 @@ #include "xformsBC.h" #include "ButtonController.h" -#include "combox.h" #include "Color.h" #include "input_validators.h" #include "forms_gettext.h" @@ -48,6 +47,8 @@ #include #include FORMS_H_LOCATION +#include "combox.h" + #include #include #include @@ -1603,7 +1604,7 @@ FD_preferences_language const * FormPreferences::Language::dialog() void FormPreferences::Language::apply(LyXRC & rc) { - int const pos = combo_default_lang->get(); + int const pos = fl_get_combox(dialog_->combox_default_lang); rc.default_language = lang_[pos-1]; int button = fl_get_button(dialog_->check_use_kbmap); @@ -1657,38 +1658,18 @@ void FormPreferences::Language::build() vector const langs = frnt::getLanguageData(false); lang_ = getSecond(langs); - // The default_language is a combo-box and has to be inserted manually - fl_freeze_form(dialog_->form); - fl_addto_form(dialog_->form); - - FL_OBJECT * obj = dialog_->choice_default_lang; - fl_deactivate_object(dialog_->choice_default_lang); - combo_default_lang.reset(new Combox(FL_COMBOX_DROPLIST)); - combo_default_lang->add(obj->x, obj->y, obj->w, obj->h, 400); - combo_default_lang->shortcut("#L",1); - combo_default_lang->setcallback(ComboCB, &parent_); - + FL_OBJECT * obj = dialog_->combox_default_lang; vector::const_iterator lit = langs.begin(); vector::const_iterator lend = langs.end(); for (; lit != lend; ++lit) { - combo_default_lang->addto(lit->first); + fl_addto_combox(obj, lit->first.c_str()); } - combo_default_lang->select(1); - - fl_end_form(); - fl_unfreeze_form(dialog_->form); + fl_set_combox_browser_height(obj, 400); // set up the feedback mechanism setPrehandler(dialog_->input_package); setPrehandler(dialog_->check_use_kbmap); - - // This is safe, as nothing is done to the pointer, other than - // to use its address in a block-if statement. - // No it's not! Leads to crash. - // setPrehandler( - // reinterpret_cast(combo_default_lang), - // C_FormPreferencesFeedbackCB); - + setPrehandler(dialog_->combox_default_lang); setPrehandler(dialog_->input_kbmap1); setPrehandler(dialog_->input_kbmap2); setPrehandler(dialog_->check_rtl_support); @@ -1709,7 +1690,7 @@ void FormPreferences::Language::build() string const FormPreferences::Language::feedback(FL_OBJECT const * const ob) const { - if (reinterpret_cast(ob) == combo_default_lang.get()) + if (ob == dialog_->combox_default_lang) return LyXRC::getDescription(LyXRC::RC_DEFAULT_LANGUAGE); if (ob == dialog_->check_use_kbmap) return LyXRC::getDescription(LyXRC::RC_KBMAP); @@ -1776,7 +1757,7 @@ void FormPreferences::Language::update(LyXRC const & rc) rc.use_kbmap); int const pos = int(findPos(lang_, rc.default_language)); - combo_default_lang->select(pos + 1); + fl_set_combox(dialog_->combox_default_lang, pos + 1); if (rc.use_kbmap) { fl_set_input(dialog_->input_kbmap1, @@ -1810,15 +1791,6 @@ void FormPreferences::Language::update(LyXRC const & rc) } -void FormPreferences::Language::ComboCB(int, void * v, Combox * combox) -{ - FormPreferences * pre = static_cast(v); - // This is safe, as nothing is done to the pointer, other than - // to use its address in a block-if statement. - pre->bc().valid(pre->input(reinterpret_cast(combox), 0)); -} - - FormPreferences::LnFmisc::LnFmisc(FormPreferences & p) : parent_(p) {} diff --git a/src/frontends/xforms/FormPreferences.h b/src/frontends/xforms/FormPreferences.h index bcf55de252..9ef2f6adfb 100644 --- a/src/frontends/xforms/FormPreferences.h +++ b/src/frontends/xforms/FormPreferences.h @@ -26,7 +26,6 @@ class ControlPrefs; -class Combox; class Dialogs; class LyXView; class RGBColor; @@ -291,8 +290,6 @@ private: bool input(FL_OBJECT const * const); /// void update(LyXRC const & rc); - /// - static void ComboCB(int, void *, Combox *); private: /// @@ -300,8 +297,6 @@ private: /// boost::scoped_ptr dialog_; /// - boost::scoped_ptr combo_default_lang; - /// std::vector lang_; }; /// diff --git a/src/frontends/xforms/Makefile.am b/src/frontends/xforms/Makefile.am index 980495d15a..ee69d247e7 100644 --- a/src/frontends/xforms/Makefile.am +++ b/src/frontends/xforms/Makefile.am @@ -18,8 +18,10 @@ libxforms_la_SOURCES = \ bmtable.h \ checkedwidgets.C \ checkedwidgets.h \ - combox.C \ + combox.c \ combox.h \ + freebrowser.c \ + freebrowser.h \ fdesign_base.C \ fdesign_base.h \ input_validators.C \ @@ -48,8 +50,6 @@ libxforms_la_SOURCES = \ ColorHandler.h \ Dialogs.C \ Dialogs2.C \ - DropDown.h \ - DropDown.C \ FileDialog.C \ FontInfo.C \ FontInfo.h \ diff --git a/src/frontends/xforms/Toolbar_pimpl.C b/src/frontends/xforms/Toolbar_pimpl.C index 9e8a2cf6d2..e5b38575de 100644 --- a/src/frontends/xforms/Toolbar_pimpl.C +++ b/src/frontends/xforms/Toolbar_pimpl.C @@ -26,6 +26,8 @@ #include "Tooltips.h" #include FORMS_H_LOCATION #include "combox.h" +#include "xforms_helpers.h" + #include "ToolbarDefaults.h" #include "LyXAction.h" @@ -84,9 +86,8 @@ Toolbar::Pimpl::toolbarItem::operator=(toolbarItem const & ti) Toolbar::Pimpl::Pimpl(LyXView * o, int x, int y) - : owner_(static_cast(o)), xpos(x), ypos(y) + : owner_(static_cast(o)), combox_(0), xpos(x), ypos(y) { - combox_ = 0; tooltip_ = new Tooltips(); } @@ -99,8 +100,6 @@ Toolbar::Pimpl::~Pimpl() //toollist.clear(); toollist_.erase(toollist_.begin(), toollist_.end()); - delete combox_; - fl_unfreeze_form(owner_->getForm()); delete tooltip_; } @@ -112,10 +111,10 @@ void Toolbar::Pimpl::update() ToolbarList::const_iterator end = toollist_.end(); for (; p != end; ++p) { if (p->action == ToolbarDefaults::LAYOUTS && combox_) { - if (owner_->getLyXFunc().getStatus(LFUN_LAYOUT).disabled()) - combox_->deactivate(); - else - combox_->activate(); + LyXFunc const & lf = owner_->getLyXFunc(); + bool const disable = + lf.getStatus(LFUN_LAYOUT).disabled(); + setEnabled(combox_, !disable); continue; } @@ -147,16 +146,25 @@ void Toolbar::Pimpl::update() } -// this one is not "C" because combox callbacks are really C++ %-| -void Toolbar::Pimpl::layoutSelectedCB(int, void * arg, Combox *) +namespace { + +void C_layoutSelectedCB(FL_OBJECT * ob, long) { - reinterpret_cast(arg)->layoutSelected(); + if (!ob || !ob->u_vdata) + return; + Toolbar::Pimpl * ptr = static_cast(ob->u_vdata); + ptr->layoutSelected(); } +} // namespace anon + void Toolbar::Pimpl::layoutSelected() { - string const & layoutguiname = combox_->getline(); + if (!combox_) + return; + + string const & layoutguiname = getString(combox_); LyXTextClass const & tc = owner_->buffer()->params.getLyXTextClass(); @@ -175,50 +183,64 @@ void Toolbar::Pimpl::layoutSelected() void Toolbar::Pimpl::setLayout(string const & layout) { - if (combox_) { - LyXTextClass const & tc = - owner_->buffer()->params.getLyXTextClass(); - combox_->select(_(tc[layout]->name())); + if (!combox_) + return; + + LyXTextClass const & tc = owner_->buffer()->params.getLyXTextClass(); + string const layoutname = _(tc[layout]->name()); + + int const nnames = fl_get_combox_maxitems(combox_); + for (int i = 1; i <= nnames; ++i) { + string const name = fl_get_combox_line(combox_, i); + if (name == layoutname) { + fl_set_combox(combox_, i); + break; + } } } void Toolbar::Pimpl::updateLayoutList(bool force) { - // Update the layout display - if (!combox_) return; + if (!combox_) + return; // If textclass is different, we need to update the list - if (combox_->empty() || force) { - combox_->clear(); + if (fl_get_combox_maxitems(combox_) == 0 || force) { + fl_clear_combox(combox_); LyXTextClass const & tc = owner_->buffer()->params.getLyXTextClass(); LyXTextClass::const_iterator end = tc.end(); for (LyXTextClass::const_iterator cit = tc.begin(); cit != end; ++cit) { // ignore obsolete entries - if ((*cit)->obsoleted_by().empty()) - combox_->addline(_((*cit)->name())); + if ((*cit)->obsoleted_by().empty()) { + string const & name = _((*cit)->name()); + fl_addto_combox(combox_, name.c_str()); + } } } // we need to do this. - combox_->redraw(); + fl_redraw_object(combox_); } void Toolbar::Pimpl::clearLayoutList() { - if (combox_) { - combox_->clear(); - combox_->redraw(); - } + if (!combox_) + return; + + fl_clear_combox(combox_); + fl_redraw_object(combox_); } void Toolbar::Pimpl::openLayoutList() { - if (combox_) - combox_->show(); + if (!combox_) + return; + + fl_show_combox_browser(combox_); } @@ -281,8 +303,6 @@ void setPixmap(FL_OBJECT * obj, int action) void Toolbar::Pimpl::add(int action) { - FL_OBJECT * obj; - toolbarItem item; item.action = action; @@ -295,15 +315,24 @@ void Toolbar::Pimpl::add(int action) break; case ToolbarDefaults::LAYOUTS: xpos += standardspacing; - if (!combox_) - combox_ = new Combox(FL_COMBOX_DROPLIST); - combox_->add(xpos, ypos, 135, height, 400); - combox_->setcallback(layoutSelectedCB, this); - combox_->resize(FL_RESIZE_ALL); - combox_->gravity(NorthWestGravity, NorthWestGravity); + if (combox_) + break; + + combox_ = fl_add_combox(FL_DROPLIST_COMBOX, + xpos, ypos, 135, height, ""); + fl_set_combox_browser_height(combox_, 400); + fl_set_object_boxtype(combox_, FL_DOWN_BOX); + fl_set_object_color(combox_, FL_MCOL, FL_MCOL); + fl_set_object_gravity(combox_, FL_NorthWest, FL_NorthWest); + fl_set_object_resize(combox_, FL_RESIZE_ALL); + + combox_->u_vdata = this; + fl_set_object_callback(combox_, C_layoutSelectedCB, 0); xpos += 135; break; - default: + default: { + FL_OBJECT * obj; + xpos += standardspacing; item.icon = obj = fl_add_pixmapbutton(FL_NORMAL_BUTTON, @@ -336,6 +365,7 @@ void Toolbar::Pimpl::add(int action) */ break; } + } toollist_.push_back(item); } diff --git a/src/frontends/xforms/Toolbar_pimpl.h b/src/frontends/xforms/Toolbar_pimpl.h index 982646c603..26db1ca671 100644 --- a/src/frontends/xforms/Toolbar_pimpl.h +++ b/src/frontends/xforms/Toolbar_pimpl.h @@ -21,15 +21,11 @@ class XFormsView; class Tooltips; -class Combox; /** The LyX xforms toolbar class */ struct Toolbar::Pimpl { public: - /// called when user selects a layout from combox - static void layoutSelectedCB(int, void *, Combox *); - /// create an empty toolbar Pimpl(LyXView * o, int x, int y); @@ -49,7 +45,7 @@ public: void openLayoutList(); /// Erase the layout list void clearLayoutList(); - /// the non-static version of layoutSelectedCB + /// void layoutSelected(); /// an item on the toolbar @@ -79,7 +75,7 @@ public: /// tooltips manager Tooltips * tooltip_; /// layout combo - Combox * combox_; + FL_OBJECT * combox_; /// x position of end of toolbar int xpos; /// y position of end of toolbar diff --git a/src/frontends/xforms/XFormsView.C b/src/frontends/xforms/XFormsView.C index 555b01f268..c93f9d32a3 100644 --- a/src/frontends/xforms/XFormsView.C +++ b/src/frontends/xforms/XFormsView.C @@ -173,8 +173,6 @@ void XFormsView::create_form_form_main(int width, int height) fl_set_form_minsize(getForm(), 50, 50); fl_end_form(); - - minibuffer_->dd_init(); } diff --git a/src/frontends/xforms/XMiniBuffer.C b/src/frontends/xforms/XMiniBuffer.C index e032ccc8ef..5a8b85bb93 100644 --- a/src/frontends/xforms/XMiniBuffer.C +++ b/src/frontends/xforms/XMiniBuffer.C @@ -13,13 +13,16 @@ #include #include "XMiniBuffer.h" -#include "DropDown.h" #include "ControlCommandBuffer.h" +#include "freebrowser.h" +#include "xforms_helpers.h" #include "gettext.h" #include "frontends/Timeout.h" +#include "support/lstrings.h" + #include #include @@ -38,6 +41,10 @@ namespace { FL_OBJECT * create_input_box(void * parent, int type, FL_Coord, FL_Coord, FL_Coord, FL_Coord); +FL_FREEBROWSER * create_freebrowser(void * parent); + +FL_OBJECT * get_freebrowser_browser(boost::shared_ptr &); + } // namespace anon @@ -47,6 +54,8 @@ XMiniBuffer::XMiniBuffer(ControlCommandBuffer & control, info_shown_(false) { input_ = create_input_box(this, FL_NORMAL_INPUT, x, y, h, w); + freebrowser_.reset(create_freebrowser(this), fl_free_freebrowser); + info_timer_.reset(new Timeout(1500)); idle_timer_.reset(new Timeout(6000)); info_con = info_timer_->timeout.connect(boost::bind(&XMiniBuffer::info_timeout, this)); @@ -61,12 +70,34 @@ XMiniBuffer::~XMiniBuffer() {} -// thanks for nothing, xforms (recursive creation not allowed) -void XMiniBuffer::dd_init() +void XMiniBuffer::freebrowserCB(int action) { - dropdown_.reset(new DropDown(input_)); - result_con = dropdown_->result.connect(boost::bind(&XMiniBuffer::set_complete_input, this, _1)); - keypress_con = dropdown_->keypress.connect(boost::bind(&XMiniBuffer::append_char, this, _1)); + if (action < 0 || action > 1) + // unrecognized action + return; + + if (action == 0) + // The freebrowser has been hidden + return; + + if (freebrowser_->last_printable) { + // Append this char to the current input contents + string input = getString(input_); + input += freebrowser_->last_printable; + fl_set_input(input_, input.c_str()); + + } else { + // Fill the input widget with the selected + // browser entry. + FL_OBJECT * browser = get_freebrowser_browser(freebrowser_); + string const str = getString(browser); + + if (!str.empty()) { + // add a space so the user can type + // an argument immediately + set_input(str + ' '); + } + } } @@ -139,6 +170,19 @@ int XMiniBuffer::peek_event(FL_OBJECT * ob, int event, set_input(new_input); + // Fill freebrowser_'s browser with the list of + // available completions + FL_OBJECT * browser = + get_freebrowser_browser(freebrowser_); + fl_clear_browser(browser); + vector::const_iterator cit = comp.begin(); + vector::const_iterator end = comp.end(); + for (; cit != end; ++cit) { + fl_add_browser_line(browser, cit->c_str()); + } + fl_select_browser_line(browser, 1); + + // Set the position of the freebrowser and display it. int x,y,w,h; fl_get_wingeometry(fl_get_real_object_window(input_), &x, &y, &w, &h); @@ -148,7 +192,9 @@ int XMiniBuffer::peek_event(FL_OBJECT * ob, int event, x += air; y += h - (input_->h + air); w = input_->w; - dropdown_->select(comp, x, y, w); + h = 100; + + fl_show_freebrowser(freebrowser_.get(), x, y-h, w, h); return 1; } case 27: @@ -242,30 +288,6 @@ void XMiniBuffer::redraw() } -void XMiniBuffer::append_char(char c) -{ - if (!c || !isprint(c)) - return; - - char const * tmp = fl_get_input(input_); - string str = tmp ? tmp : ""; - - str += c; - - fl_set_input(input_, str.c_str()); -} - - -void XMiniBuffer::set_complete_input(string const & str) -{ - if (!str.empty()) { - // add a space so the user can type - // an argument immediately - set_input(str + ' '); - } -} - - void XMiniBuffer::message(string const & str) { if (!isEditingMode()) @@ -291,6 +313,17 @@ int C_XMiniBuffer_peek_event(FL_OBJECT * ob, int event, } +extern "C" +void C_freebrowserCB(FL_FREEBROWSER * fb, int action) +{ + if (!fb || !fb->parent) + return; + + XMiniBuffer * ptr = static_cast(fb->parent); + ptr->freebrowserCB(action); +} + + FL_OBJECT * create_input_box(void * parent, int type, FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h) { @@ -309,4 +342,19 @@ FL_OBJECT * create_input_box(void * parent, int type, return obj; } + +FL_FREEBROWSER * create_freebrowser(void * parent) +{ + FL_FREEBROWSER * fb = fl_create_freebrowser(parent); + fb->want_printable = 1; + fb->callback = C_freebrowserCB; + return fb; +} + +FL_OBJECT * get_freebrowser_browser(boost::shared_ptr & fb) +{ + FL_FREEBROWSER * ptr = fb.get(); + return ptr ? fl_get_freebrowser_browser(ptr) : 0; +} + } // namespace anon diff --git a/src/frontends/xforms/XMiniBuffer.h b/src/frontends/xforms/XMiniBuffer.h index 3785aebaa1..d81472ef7d 100644 --- a/src/frontends/xforms/XMiniBuffer.h +++ b/src/frontends/xforms/XMiniBuffer.h @@ -18,9 +18,12 @@ #include "LString.h" #include +#include #include -class DropDown; +struct fl_freebrowser_; +typedef fl_freebrowser_ FL_FREEBROWSER; + class ControlCommandBuffer; class Timeout; @@ -34,9 +37,6 @@ public: /// ~XMiniBuffer(); - /// create drop down - void dd_init(); - /// repaint the minibuffer void redraw(); @@ -52,6 +52,9 @@ public: /// disable event management void freeze(); + /// xforms callback routine + void freebrowserCB(int action); + private: /// Are we in editing mode? bool isEditingMode() const; @@ -62,15 +65,6 @@ private: /// go back to "at rest" message void idle_timeout(); - /** - * Append "c" to the current input contents when the completion - * list is displayed and has focus. - */ - void append_char(char c); - - /// completion selection callback - void set_complete_input(string const & str); - /// set the minibuffer content in editing mode void set_input(string const &); @@ -81,7 +75,7 @@ private: void show_info(string const & info, string const & input, bool append = true); /// the dropdown menu - boost::scoped_ptr dropdown_; + boost::shared_ptr freebrowser_; /// info timer boost::scoped_ptr info_timer_; diff --git a/src/frontends/xforms/combox.C b/src/frontends/xforms/combox.C deleted file mode 100644 index 00f27bc5af..0000000000 --- a/src/frontends/xforms/combox.C +++ /dev/null @@ -1,556 +0,0 @@ -/** - * \file combox.C - * Copyright 1996Alejandro Aguilar Sierra - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author Alejandro Aguilar Sierra - * - * Full author contact details are available in file CREDITS - */ - -/* A combination of two objects (a button and a browser) is encapsulated to - * get a combobox-like object. All XForms functions are hidden. - * - */ - -/* Change log: - * - * 2/06/1996, Alejandro Aguilar Sierra - * Created and tested. - * - * 4/06/1996, Alejandro Aguilar Sierra - * Added droplist mode (a button with a black down arrow at right) - * and support for middle and right buttons, as XForms choice object. - * - * 6/06/1996, Lars Gullik Bjønnes - * Added a combox with an input object. and a pre and a post handle. - * - * 22/07/96, Alejandro Aguilar Sierra - * Assigned to the browser its own popup window. No more need of - * external pre and post handlers to simulate the wanted behaviour. - * - */ - -#include - - -#include "combox.h" -//#include - -#include "debug.h" - -using std::endl; - -// These are C wrappers around static members of Combox, used as -// callbacks for xforms. -extern "C" { - - static - void C_Combox_input_cb(FL_OBJECT * ob, long data) - { - Combox::input_cb(ob, data); - } - - static - void C_Combox_combo_cb(FL_OBJECT * ob, long data) - { - Combox::combo_cb(ob, data); - } - - static - int C_Combox_peek_event(FL_FORM * form, void *xev) - { - return Combox::peek_event(form, xev); - } - -} - - -Combox::Combox(combox_type t) - : type(t) -{ - browser = button = 0; - callback = 0; - label = 0; - cb_arg = 0; - _pre = 0; - _post = 0; - sel = 0; - form = 0; -} - - -Combox::~Combox() -{ - // This is now handled by the XFormsView destructor (Lgb) - // remove(); -} - - -void Combox::clear() -{ - if (browser) fl_clear_browser(browser); - sel = 0; - if (type == FL_COMBOX_INPUT) - fl_set_input(label, ""); - else - fl_set_object_label(label, ""); - is_empty = true; -} - - -void Combox::remove() -{ - lyxerr[Debug::GUI] << "Button: " << button << endl; - if (button) { - fl_delete_object(button); - fl_free_object(button); - } - - lyxerr[Debug::GUI] << "Label: " << label << endl; - if (label && label != button) { - fl_delete_object(label); - fl_free_object(label); - } - - lyxerr[Debug::GUI] << "Form: " << form << endl; - lyxerr[Debug::GUI] << "Browser: " << browser << endl; - if (form && browser) { - fl_delete_object(browser); - fl_free_object(browser); - fl_free_form(form); - } - button = 0; - browser = 0; - label = 0; - form = 0; - sel = 0; - is_empty = true; -} - - -void Combox::addline(string const & text) -{ - if (!browser) return; - fl_add_browser_line(browser, text.c_str()); - - // By default the first item is selected - if (!sel) { - sel = 1; - if (type == FL_COMBOX_INPUT) - fl_set_input(label, text.c_str()); - else - fl_set_object_label(label, text.c_str()); - } - is_empty = false; -} - - -bool Combox::select(string const & t) -{ - if (!browser || t.empty()) return false; - int const maxline = fl_get_browser_maxline(browser); - - for (int i = 1; i <= maxline; ++i) { - if (t == fl_get_browser_line(browser, i)) { - select(i); - return true; - } - } - return false; // t does not exist in browser -} - - -void Combox::select(int i) -{ - if (!browser || !button) return; - if (i > 0 && i <= fl_get_browser_maxline(browser)) sel = i; - fl_deactivate_object(button); - - if (type == FL_COMBOX_INPUT) - fl_set_input(label, fl_get_browser_line(browser, sel)); - else - fl_set_object_label(label, fl_get_browser_line(browser, sel)); - fl_activate_object(button); -} - - -void Combox::add(int x, int y, int w, int hmin, int hmax) -{ - FL_OBJECT * obj; - - switch (type) { - case FL_COMBOX_DROPLIST: - { - button = obj = fl_add_button(FL_NORMAL_BUTTON, - x+w-22, y, 22, hmin, "@2->"); - fl_set_object_color(obj, FL_MCOL, FL_MCOL); - fl_set_object_dblbuffer(obj, 1); - fl_set_object_callback(obj, C_Combox_combo_cb, 0); - label = obj = fl_add_button(FL_NORMAL_TEXT, x, y, w-22, hmin, ""); - fl_set_object_boxtype(obj, FL_DOWN_BOX); - fl_set_object_color(obj, FL_MCOL, FL_BLACK); - fl_set_object_lalign(obj, FL_ALIGN_CENTER|FL_ALIGN_INSIDE); - fl_set_object_dblbuffer(obj, 1); - fl_set_object_callback(obj, C_Combox_combo_cb, 0); - break; - } - case FL_COMBOX_NORMAL: - { - button = obj = fl_add_button(FL_NORMAL_BUTTON, x, y, w, hmin, ""); - fl_set_object_color(obj, FL_MCOL, FL_MCOL); - fl_set_object_boxtype(obj, FL_DOWN_BOX); - fl_set_object_callback(obj, C_Combox_combo_cb, 0); - fl_set_object_color(obj, FL_MCOL, FL_BLACK); - label = button; - break; - } - case FL_COMBOX_INPUT: - { - button = obj = fl_add_button(FL_NORMAL_BUTTON, - x+w-22, y, 22, hmin, "@2->"); - fl_set_object_color(obj, FL_MCOL, FL_MCOL); - fl_set_object_callback(obj, C_Combox_combo_cb, 0); - label = obj = fl_add_input(FL_NORMAL_INPUT, x, y, w-22, hmin, ""); - fl_set_object_boxtype(obj, FL_DOWN_BOX); - fl_set_object_return(obj, FL_RETURN_END_CHANGED); - fl_set_object_callback(obj, C_Combox_input_cb, 0); - //fl_set_object_color(obj, FL_MCOL, FL_BLACK); - //fl_set_object_lalign(obj,FL_ALIGN_CENTER|FL_ALIGN_INSIDE); - break; - } - } // end of switch - - label->u_vdata = this; - button->u_vdata = this; - - // Hmm, it seems fl_create_browser is broken in xforms 0.86. - // We have to work around that by creating the dropped browser form - // at this point already. However, this means that we have - // to do a little hacking: (Asger) - FL_FORM * current_form = fl_current_form; - fl_end_form(); - - bw = w + 20; - bh = hmax - hmin - 12; - - form = fl_bgn_form(FL_NO_BOX, bw, bh); - browser = obj = fl_add_browser(FL_HOLD_BROWSER, 0, 0, bw, bh, ""); - fl_set_object_boxtype(obj, FL_UP_BOX); - fl_set_object_color(obj, FL_MCOL, FL_YELLOW); - fl_set_object_gravity(obj, NorthWestGravity, NorthWestGravity); - fl_set_object_callback(obj, C_Combox_combo_cb, 2); - fl_end_form(); - browser->u_vdata = this; - form->u_vdata = browser; - fl_register_raw_callback(form, - ButtonPressMask|KeyPressMask, - C_Combox_peek_event); - - // And revert to adding to the old form (Asger) - fl_addto_form(current_form); -} - - -namespace { - -Window save_window; - -} // namespace anon - - -void Combox::redraw() -{ - if (browser) fl_redraw_object(browser); - if (button) fl_redraw_object(button); - if (label) fl_redraw_object(label); -} - -void Combox::show() -{ - if (_pre) _pre(); - - int tmp; - XGetInputFocus(fl_get_display(), &save_window, &tmp); //BUG-Fix Dietmar - XFlush(fl_get_display()); - if (button && type != FL_COMBOX_NORMAL) { - fl_set_object_label(button, "@2<-"); - fl_redraw_object(button); - } - - int const x = label->form->x + label->x; - int const y = label->form->y + label->y + label->h; - - fl_set_form_position(form, x, y); - fl_show_form(form, FL_PLACE_POSITION, FL_NOBORDER, ""); - if (sel > 0) { - fl_set_browser_topline(browser, sel); - fl_select_browser_line(browser, sel); - } - XGrabPointer(fl_get_display(), form->window, false, - ButtonPressMask | ButtonReleaseMask | PointerMotionMask, - GrabModeAsync, GrabModeAsync, - 0, 0, 0); - XFlush(fl_get_display()); -} - -void Combox::hide(int who) -{ - if (!who && browser && label) { - sel = fl_get_browser(browser); - - if (type == FL_COMBOX_INPUT) - fl_set_input(label, fl_get_browser_line(browser, sel)); - else - fl_set_object_label(label, - fl_get_browser_line(browser, sel)); -// if (callback) callback(sel, cb_arg); - } - XUngrabPointer(fl_get_display(), 0); - XFlush(fl_get_display()); - if (form) { - fl_hide_form(form); - XSetInputFocus(fl_get_display(), save_window, - RevertToParent, CurrentTime); // BUG-FIX-Dietmar - XFlush(fl_get_display()); - } - if (button) { - if (type != FL_COMBOX_NORMAL) { - fl_set_object_label(button, "@2->"); - fl_redraw_object(button); - } - } - if (!who && browser && label && callback) - callback(sel, cb_arg, this); - if (_post) _post(); -} - - -void Combox::activate() -{ - if (browser) - fl_activate_object(browser); - if (button) { - fl_activate_object(button); - fl_set_object_lcol(button, FL_BLACK); - } - if (label) { - fl_activate_object(label); - fl_set_object_lcol(label, FL_BLACK); - } -} - - -void Combox::deactivate() -{ - if (browser) - fl_deactivate_object(browser); - if (button) { - fl_deactivate_object(button); - fl_set_object_lcol(button, FL_INACTIVE); - } - if (label) { - fl_deactivate_object(label); - fl_set_object_lcol(label, FL_INACTIVE); - } -} - - -void Combox::input_cb(FL_OBJECT * ob, long) -{ - Combox * combo = static_cast(ob->u_vdata); - - char const * text = fl_get_input(ob); - - combo->addto(text ? string(text) : string()); - combo->is_empty = false; -} - - -void Combox::combo_cb(FL_OBJECT * ob, long data) -{ - Combox * combo = static_cast(ob->u_vdata); - switch (data) { - case 0: - { - int const i = combo->get(); - switch (fl_get_button_numb(ob)) { - case 2: - { - combo->select(i - 1); - if (combo->callback) - combo->callback(combo->sel, - combo->cb_arg, combo); - break; - } - case 3: - { - combo->select(i + 1); - if (combo->callback) - combo->callback(combo->sel, - combo->cb_arg, combo); - break; - } - default: combo->show(); break; - } - break; - } - case 2: - combo->hide(); - break; - } -} - - -int Combox::peek_event(FL_FORM * form, void * xev) -{ - FL_OBJECT * ob = static_cast(form->u_vdata); - Combox * combo = static_cast(ob->u_vdata); - - // below mouse does not work like we need it - if (static_cast(xev)->type == ButtonPress && ( - static_cast(xev)->xbutton.x - ob->x < 0 || - static_cast(xev)->xbutton.x - ob->x > ob->w || - static_cast(xev)->xbutton.y - ob->y < 0 || - static_cast(xev)->xbutton.y - ob->y > ob->h)) { - combo->hide(1); - return 1; - } - - if (static_cast(xev)->type != KeyPress) return 0; - - char s_r[10]; s_r[9] = '\0'; - KeySym keysym_return; - XLookupString(&static_cast(xev)->xkey, s_r, 10, - &keysym_return, 0); - XFlush(fl_get_display()); - switch (keysym_return) { - case XK_Down: -#ifdef XK_KP_Down - case XK_KP_Down: -#endif - if (fl_get_browser(combo->browser) < - fl_get_browser_maxline(combo->browser)) - fl_select_browser_line(combo->browser, - fl_get_browser(combo->browser)+1); - if (fl_get_browser(combo->browser)>= - fl_get_browser_topline(combo->browser) + - fl_get_browser_screenlines(combo->browser)) - fl_set_browser_topline(combo->browser, - fl_get_browser(combo->browser) - - fl_get_browser_screenlines(combo->browser)+1); - if (fl_get_browser(combo->browser)< - fl_get_browser_topline(combo->browser)) - fl_set_browser_topline(combo->browser, - fl_get_browser(combo->browser)); - return 1; - case XK_Up: -#ifdef XK_KP_Up - case XK_KP_Up: -#endif - if (fl_get_browser(combo->browser) > 1) - fl_select_browser_line(combo->browser, - fl_get_browser(combo->browser)-1); - if (fl_get_browser(combo->browser)>= - fl_get_browser_topline(combo->browser) + - fl_get_browser_screenlines(combo->browser)) - fl_set_browser_topline(combo->browser, - fl_get_browser(combo->browser) - - fl_get_browser_screenlines(combo->browser)+1); - if (fl_get_browser(combo->browser) < - fl_get_browser_topline(combo->browser)) - fl_set_browser_topline(combo->browser, - fl_get_browser(combo->browser)); - return 1; - case XK_Return: -#ifdef XK_KP_Enter - case XK_KP_Enter: -#endif - combo->hide(); - return 1; - case XK_Escape: - combo->hide(1); - return 1; - } - return 0; -} - - -#ifdef TESTCOMBO -typedef struct { - FL_FORM *test; - FL_OBJECT *bar; - void *vdata; - long ldata; -} FD_test; - -//Combox combo(FL_COMBOX_DROPLIST); -Combox combo(FL_COMBOX_INPUT); - -FD_test *fd_test; - -FD_test *create_form_test(void) -{ - FL_OBJECT *obj; - FD_test *fdui = (FD_test *) fl_calloc(1, sizeof(*fdui)); - - fdui->test = fl_bgn_form(FL_NO_BOX, 320, 190); - obj = fl_add_box(FL_UP_BOX, 0, 0, 320, 190, ""); - obj = fl_add_box(FL_DOWN_BOX, 10, 50, 300, 110, ""); - obj = fl_add_button(FL_NORMAL_BUTTON, 250, 10, 50, 30, _("Done")); - combo.add(10, 15, 120, 25, 135); - fl_end_form(); - - return fdui; -} - -void combo_cb(int i) -{ - fprintf(stderr, "selected %d:%s\n", i, combo.getline()); -} - -int main(int argc, char *argv[]) -{ - //int n1; - - // Same defaults as in lyx - FL_IOPT cntl; - cntl.buttonFontSize = FL_NORMAL_SIZE; - cntl.browserFontSize = FL_NORMAL_SIZE; - cntl.labelFontSize = FL_NORMAL_SIZE; - cntl.choiceFontSize = FL_NORMAL_SIZE; - cntl.inputFontSize = FL_NORMAL_SIZE; - cntl.borderWidth = -2; - fl_set_defaults(FL_PDButtonFontSize, &cntl); - fl_set_defaults(FL_PDBrowserFontSize, &cntl); - fl_set_defaults(FL_PDLabelFontSize, &cntl); - fl_set_defaults(FL_PDChoiceFontSize, &cntl); - fl_set_defaults(FL_PDInputFontSize, &cntl); - fl_set_defaults(FL_PDBorderWidth, &cntl); - fl_initialize(&argc, argv, 0, 0, 0); - - fd_test = create_form_test(); - - /* fill-in form initialization code */ - combo.addline("Title"); - combo.addline("Author"); - combo.addline("Date"); - combo.addline("Abstract"); - combo.addline("Chapter"); - combo.addline("Section"); - combo.addline("Subsection"); - combo.addline("List"); - combo.addline("Description"); - combo.addline("Verse"); - combo.addline("Verbatim"); - combo.setcallback(combo_cb); -// combo.select(4); - - /* show the first form */ - fl_show_form(fd_test->test, FL_PLACE_CENTER, FL_FULLBORDER, "test"); - fl_do_forms(); - return 0; -} - -#endif diff --git a/src/frontends/xforms/combox.c b/src/frontends/xforms/combox.c new file mode 100644 index 0000000000..3dc9bea9c3 --- /dev/null +++ b/src/frontends/xforms/combox.c @@ -0,0 +1,460 @@ +/** + * \file combox.c + * + * \author Alejandro Aguilar Sierra + * \author Angus Leeming + * + * This is a rewrite of Alejandro's C++ Combox class, originally written + * for LyX in 1996. The rewrite turns it into a native xforms widget. + */ +#include + +#include FORMS_H_LOCATION +#include "combox.h" +#include "freebrowser.h" + + +extern void fl_add_child(FL_OBJECT *, FL_OBJECT *); +extern void fl_addto_freelist(void *); + + +typedef struct { + /** A pointer to the parent widget */ + FL_OBJECT * combox; + + FL_FREEBROWSER * browser; + int browser_height; + + /** The browser will be displayed either below or above the main body. */ + int browser_position; + + /** button_state displays a down or up arrow depending on whether the + * browser is visible or not. + * Click on it to toggle the browser. + */ + FL_OBJECT * button_state; + + /** button_chosen displays the current selection from the browser. + * Click on it to toggle the browser. + */ + FL_OBJECT * button_chosen; +} COMBOX_SPEC; + + +enum { ACTIVATE, DEACTIVATE }; + +enum { COMBOX_OPEN, COMBOX_CLOSED }; + + +/* function declarations */ +static int combox_pre(FL_OBJECT *, int, FL_Coord, FL_Coord, int, void *); +static int combox_post(FL_OBJECT *, int, FL_Coord, FL_Coord, int, void *); +static int combox_handle(FL_OBJECT *, int, FL_Coord, FL_Coord, int, void *); + +static void update_button_chosen(FL_FREEBROWSER * fb, int action); +static void chosen_cb(FL_OBJECT * ob, long data); +static void state_cb(FL_OBJECT * ob, long data); + +static void show_browser(COMBOX_SPEC * sp); +static void set_activation(FL_OBJECT * ob, int activation); +static void set_state_label(COMBOX_SPEC * sp, int state); +static void attrib_change(COMBOX_SPEC * sp); + + +FL_OBJECT * fl_create_combox(int type, + FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h, + char const * label) +{ + FL_OBJECT * ob; + FL_OBJECT * button; + COMBOX_SPEC * sp; + + /* The width and x-position of button_state, respectively. */ + FL_Coord const ws = 0.7 * h; + FL_Coord const xs = x + w - ws; + + ob = fl_make_object(FL_COMBOX, type, x, y, w, h, label, combox_handle); + ob->align = FL_ALIGN_LEFT; + + sp = ob->spec = fl_calloc(1, sizeof(COMBOX_SPEC)); + sp->combox = ob; + sp->browser_height = 100; + sp->browser_position = FL_FREEBROWSER_BELOW; + + sp->browser = fl_create_freebrowser(sp); + sp->browser->callback = update_button_chosen; + + sp->button_state = fl_add_button(FL_NORMAL_BUTTON, xs, y, ws, h, ""); + + button = sp->button_state; + fl_set_object_lalign(button, FL_ALIGN_CENTER|FL_ALIGN_INSIDE); + fl_set_object_callback(button, state_cb, 0); + fl_set_object_posthandler(button, combox_post); + fl_set_object_prehandler(button, combox_pre); + set_state_label(sp, COMBOX_CLOSED); + + set_activation(button, DEACTIVATE); + button->parent = ob; + button->u_vdata = sp; + + sp->button_chosen = fl_add_button(FL_NORMAL_TEXT, x, y, (w - ws), h, ""); + + button = sp->button_chosen; + fl_set_object_boxtype(button, FL_FRAME_BOX); + fl_set_object_lalign(button, FL_ALIGN_CENTER|FL_ALIGN_INSIDE); + fl_set_object_callback(button, chosen_cb, 0); + fl_set_object_posthandler(button, combox_post); + fl_set_object_prehandler(button, combox_pre); + set_activation(button, DEACTIVATE); + button->parent = ob; + button->u_vdata = sp; + + return ob; +} + + +FL_OBJECT * fl_add_combox(int type, + FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h, + char const * label) +{ + FL_OBJECT * ob = fl_create_combox(type, x, y, w, h, label); + COMBOX_SPEC * sp = ob->spec; + + fl_add_child(ob, sp->button_state); + fl_add_child(ob, sp->button_chosen); + + fl_add_object(fl_current_form, ob); + return ob; +} + + +void fl_set_combox_browser_height(FL_OBJECT * ob, int bh) +{ + COMBOX_SPEC * sp; + + if (!ob || ob->objclass != FL_COMBOX) + return; + + sp = ob->spec; + sp->browser_height = bh; +} + + +void fl_set_combox_position(FL_OBJECT * ob, int position) +{ + COMBOX_SPEC * sp; + + if (!ob || ob->objclass != FL_COMBOX) + return; + + sp = ob->spec; + sp->browser_position = (position == FL_FREEBROWSER_ABOVE) ? + FL_FREEBROWSER_ABOVE : FL_FREEBROWSER_BELOW; + + set_state_label(sp, COMBOX_CLOSED); +} + + +void fl_clear_combox(FL_OBJECT * ob) +{ + COMBOX_SPEC * sp; + FL_OBJECT * browser; + + if (!ob || ob->objclass != FL_COMBOX) + return; + + sp = ob->spec; + browser = fl_get_freebrowser_browser(sp->browser); + + fl_clear_browser(browser); + fl_set_object_label(sp->button_chosen, ""); +} + + +void fl_addto_combox(FL_OBJECT * ob, char const * text) +{ + COMBOX_SPEC * sp; + FL_OBJECT * browser; + int i; + int j; + char line[128]; + + if (!ob || ob->objclass != FL_COMBOX) + return; + + sp = ob->spec; + browser = fl_get_freebrowser_browser(sp->browser); + + /* Split the string on '|' boundaries. */ + i = j = 0; + for (; text[i] != '\0'; ++i) { + if (text[i] == '|') { + line[j] = '\0'; + fl_add_browser_line(browser, line); + j = 0; + } else { + line[j++] = text[i]; + } + } + + if (j != 0) + { + line[j] = '\0'; + fl_add_browser_line(browser, line); + } + + /* By default the first item is selected */ + if (!fl_get_browser(browser)) { + fl_set_object_label(sp->button_chosen, text); + set_activation(sp->button_chosen, ACTIVATE); + set_activation(sp->button_state, ACTIVATE); + } +} + + +void fl_set_combox(FL_OBJECT * ob, int sel) +{ + COMBOX_SPEC * sp; + FL_OBJECT * browser; + + if (!ob || ob->objclass != FL_COMBOX) + return; + + sp = ob->spec; + browser = fl_get_freebrowser_browser(sp->browser); + + if (sel < 1 || sel > fl_get_browser_maxline(browser)) + return; + + fl_select_browser_line(browser, sel); + fl_set_object_label(sp->button_chosen, fl_get_browser_line(browser, sel)); +} + + +int fl_get_combox(FL_OBJECT * ob) +{ + COMBOX_SPEC * sp; + FL_OBJECT * browser; + + if (!ob || ob->objclass != FL_COMBOX) + return 0; + + sp = ob->spec; + browser = fl_get_freebrowser_browser(sp->browser); + return fl_get_browser(browser); +} + + +char const * fl_get_combox_text(FL_OBJECT * ob) +{ + COMBOX_SPEC * sp; + + if (!ob || ob->objclass != FL_COMBOX) + return 0; + + sp = ob->spec; + return sp->button_chosen->label; +} + + +char const * fl_get_combox_line(FL_OBJECT * ob, int line) +{ + COMBOX_SPEC * sp; + FL_OBJECT * browser; + int maxlines; + + if (line < 1 || !ob || ob->objclass != FL_COMBOX) + return 0; + + sp = ob->spec; + browser = fl_get_freebrowser_browser(sp->browser); + + maxlines = fl_get_browser_maxline(browser); + if (line > maxlines) + return 0; + + return fl_get_browser_line(browser, line); +} + + +int fl_get_combox_maxitems(FL_OBJECT * ob) +{ + COMBOX_SPEC * sp; + FL_OBJECT * browser; + + if (!ob || ob->objclass != FL_COMBOX) + return 0; + + sp = ob->spec; + browser = fl_get_freebrowser_browser(sp->browser); + return fl_get_browser_maxline(browser); +} + + +void fl_show_combox_browser(FL_OBJECT * ob) +{ + if (!ob || ob->objclass != FL_COMBOX) + return; + + show_browser(ob->spec); +} + + +void fl_hide_combox_browser(FL_OBJECT * ob) +{ + COMBOX_SPEC * sp; + + if (!ob || ob->objclass != FL_COMBOX) + return; + + sp = ob->spec; + fl_free_freebrowser(sp->browser); +} + + +static int combox_pre(FL_OBJECT * ob, int ev, FL_Coord mx, FL_Coord my, + int key, void *xev) +{ + COMBOX_SPEC * sp = ob->u_vdata; + FL_OBJECT * combox = sp->combox; + + return combox->prehandle ? + combox->prehandle(combox, ev, mx, my, key, xev) : 0; +} + + +static int combox_post(FL_OBJECT * ob, int ev, FL_Coord mx, FL_Coord my, + int key, void *xev) +{ + COMBOX_SPEC * sp = ob->u_vdata; + FL_OBJECT * combox = sp->combox; + + return combox->posthandle ? + combox->posthandle(combox, ev, mx, my, key, xev) : 0; +} + + +static int combox_handle(FL_OBJECT * ob, int event, FL_Coord mx, FL_Coord my, + int key, void * ev) +{ + if (!ob || ob->objclass != FL_COMBOX) + return 0; + + switch (event) { + case FL_DRAW: + attrib_change(ob->spec); + /* Fall through */ + case FL_DRAWLABEL: + fl_draw_object_label(ob); + break; + case FL_SHORTCUT: + show_browser(ob->spec); + break; + case FL_FREEMEM: { + COMBOX_SPEC * sp = ob->spec; + fl_free_freebrowser(sp->browser); + /* children take care of themselves, but we must make sure that + sp itself is free-d eventually. */ + fl_addto_freelist(sp); + break; + } + } + return 0; +} + + +static void set_activation(FL_OBJECT * ob, int activation) +{ + switch (activation) { + case ACTIVATE: + fl_activate_object(ob); + fl_set_object_lcol(ob, FL_LCOL); + break; + case DEACTIVATE: + fl_deactivate_object(ob); + fl_set_object_lcol(ob, FL_INACTIVE); + } +} + + +static void show_browser(COMBOX_SPEC * sp) +{ + FL_OBJECT * ob = sp->combox; + + /* The browser dimensions. */ + FL_Coord const bw = ob->w + 20; + FL_Coord const bh = sp->browser_height; + + FL_Coord const abs_x = ob->form->x + ob->x; + + FL_Coord abs_y = ob->form->y + ob->y; + abs_y += (sp->browser_position == FL_FREEBROWSER_BELOW) ? ob->h : -bh; + + set_state_label(sp, COMBOX_OPEN); + fl_show_freebrowser(sp->browser, abs_x, abs_y, bw, bh); +} + + +static void state_cb(FL_OBJECT * ob, long data) +{ + show_browser(ob->u_vdata); +} + + +static void chosen_cb(FL_OBJECT * ob, long data) +{ + show_browser(ob->u_vdata); +} + + +static void update_button_chosen(FL_FREEBROWSER * fb, int action) +{ + COMBOX_SPEC * sp = fb->parent; + + FL_OBJECT * browser = fl_get_freebrowser_browser(sp->browser); + FL_OBJECT * combox = sp->combox; + if (!browser || !combox) return; + + set_state_label(sp, COMBOX_CLOSED); + + if (action == 1) { + int const sel = fl_get_browser(browser); + char const * const text = fl_get_browser_line(browser, sel); + fl_set_object_label(sp->button_chosen, text); + fl_call_object_callback(combox); + } +} + + +static void set_state_label(COMBOX_SPEC * sp, int state) +{ + char const * const up = "@2<-"; + char const * const down = "@2->"; + char const * label = 0; + if (sp->browser_position == FL_FREEBROWSER_BELOW) { + label = (state == COMBOX_OPEN) ? up : down; + } else { + label = (state == COMBOX_OPEN) ? down : up; + } + fl_set_object_label(sp->button_state, label); + fl_redraw_object(sp->button_state); +} + + +static void attrib_change(COMBOX_SPEC * sp) +{ + FL_OBJECT * parent = sp->combox; + FL_OBJECT * button = sp->button_chosen; + + button->boxtype = parent->boxtype; + button->col1 = parent->col1; + button->col2 = parent->col2; + button->bw = parent->bw; + + button = sp->button_state; + + /* The boxtype is not changed */ + button->col1 = parent->col1; + button->col2 = parent->col2; + button->bw = parent->bw; +} diff --git a/src/frontends/xforms/combox.h b/src/frontends/xforms/combox.h index 8b901944eb..50cdb6aa8c 100644 --- a/src/frontends/xforms/combox.h +++ b/src/frontends/xforms/combox.h @@ -1,231 +1,87 @@ -// -*- C++ -*- /** * \file combox.h - * Copyright 1996 Alejandro Aguilar Sierra - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. + * \author Angus Leeming * - * \author Alejandro Aguilar Sierra - * - * Full author contact details are available in file CREDITS - */ - -/* A combination of two objects (a button and a browser) is encapsulated to - * get a combobox-like object. All XForms functions are hidden. - * - * Change log: - * - * 2/06/1996, Alejandro Aguilar Sierra - * Created and tested. - * - * 4/06/1996, Alejandro Aguilar Sierra - * Added droplist mode (a button with a black down arrow at right) - * and support for middle and right buttons, as XForms choice object. + * A combination of two objects (a button and a browser) is encapsulated to + * get a combobox-like object. */ -#ifndef COMBOX_H -#define COMBOX_H - +#ifndef FL_COMBOX_H +#define FL_COMBOX_H -#include FORMS_H_LOCATION -#include -#include "LString.h" +#if defined(__cplusplus) +extern "C" +{ +#endif -/// -enum combox_type { - /// - FL_COMBOX_NORMAL, - /// - FL_COMBOX_DROPLIST, - /// - FL_COMBOX_INPUT +/** This will eventually be moved into the enum of in-built widgets + in forms.h. */ +enum { + FL_COMBOX = 200 }; -class Combox; - -/// callback prototype -typedef void (*FL_COMBO_CB) (int, void *, Combox *); -/// pre post prototype -typedef void (*FL_COMBO_PRE_POST) (); - - -/// -class Combox { -public: - /// - explicit Combox(combox_type t = FL_COMBOX_NORMAL); - /// - ~Combox(); - - /** To add this object to a form. Note that there are two heights - * for normal (button) and expanded (browser) mode each. - */ - void add(int x, int y, int w, int hmin, int hmax); - - /// Add lines. Same as for fl_browser object - void addline(string const &); - /// Add lines. Same as for fl_browser object - void addto(string const &); - - /// Returns the selected item - int get() const; - - /// Returns a pointer to the selected line of text - string const getline() const; - - /// Select an arbitrary item - void select(int); - /// - bool select(string const &); - - /// Clear all the list - void clear(); - - /// Is the combox cleared (empty) - bool empty() const { return is_empty; } - - /// Remove the objects from the form they are in. - void remove(); - - /** - * Assign a callback to this object. The callback should be a void - * function with a int, a void pointer, and a Combox pointer as - * parameters. - */ - void setcallback(FL_COMBO_CB, void *); - - /// Pre handler - void setpre(FL_COMBO_PRE_POST); - /// Post handler - void setpost(FL_COMBO_PRE_POST); - - /// XForms attributes - void resize(unsigned); - /// - void gravity(unsigned, unsigned); - /// - void activate(); - /// - void deactivate(); - /// - void shortcut(string const &, int); - /// - void redraw(); - /// - void show(); - /// - static void combo_cb(FL_OBJECT *, long); - /// - static void input_cb(FL_OBJECT *, long); - /// - static int peek_event(FL_FORM *, void *); - protected: - /// At least Hide should not be public - void hide(int who = 0); - /// - FL_OBJECT * browser; - private: - /// - combox_type type; - /// - int bw; - /// - int bh; - /// - int sel; - /// - bool is_empty; - /// - FL_COMBO_CB callback; - /// - void * cb_arg; - /// - FL_COMBO_PRE_POST _pre; - /// - FL_COMBO_PRE_POST _post; - /// - FL_OBJECT * button; - /// - FL_OBJECT * label; - /// - FL_FORM* form; +/** The types of combox. At the moment, there's only one. */ +enum { + FL_DROPLIST_COMBOX }; +/** A function to create a combox widget. + * \param type is, as yet, unused. there is only one type of combox. + * \param x, \param y: the x,y coordinates of the upper left hand corner + * of the widget, relative to the parent form'd origin. + * \param w, \param h: the widget's dimensions. + * \param label: the widget's label as it appears on the GUI. + */ +FL_EXPORT FL_OBJECT * +fl_create_combox(int type, FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h, + char const * label); +/** A function to create a combox widget and add it to the parent form. + * \see fl_create_combox() for an explanation of the argument list. + */ +FL_EXPORT FL_OBJECT * +fl_add_combox(int type, FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h, + char const * label); -//----------------- Inline methods --------------------------- - -inline -void Combox::addto(string const & text) -{ - if (browser) { - fl_addto_browser(browser, text.c_str()); - is_empty = false; - } -} - - -inline -void Combox::resize(unsigned r) -{ - fl_set_object_resize(button, r); - if (label!= button) fl_set_object_resize(label, r); -} - - -inline -void Combox::gravity(unsigned g1, unsigned g2) -{ - fl_set_object_gravity(button, g1, g2); - if (label!= button) fl_set_object_gravity(label, g1, g2); -} - +/** The combox browser has a default height of 100 pixels. Adjust to suit. */ +FL_EXPORT void fl_set_combox_browser_height(FL_OBJECT * ob, int bh); -inline -void Combox::shortcut(string const & s, int i) -{ - if (button) - fl_set_object_shortcut(button, s.c_str(), i); -} +/** The browser will be displayed either below or above the button, + * dependent upon \param position. + */ +FL_EXPORT void fl_set_combox_position(FL_OBJECT * ob, int position); +/** Empty the browser and the combox, \param ob. */ +FL_EXPORT void fl_clear_combox(FL_OBJECT * ob); -inline -void Combox::setcallback(FL_COMBO_CB cb, void * a = 0) -{ - callback = cb; - cb_arg = a; -} +/** Add a line to the combox browser.*/ +FL_EXPORT void fl_addto_combox(FL_OBJECT * ob, char const * text); +/** Set the combox to return line \param choice of the combox browser. */ +FL_EXPORT void fl_set_combox(FL_OBJECT * ob, int choice); -inline -void Combox::setpre(FL_COMBO_PRE_POST cb) -{ - _pre = cb; -} +/** \return the currently selected line of the combox browser. */ +FL_EXPORT int fl_get_combox(FL_OBJECT * ob); +/** \return the contents of the combox. + * (Also the contents of currently selected line of the combox browser.) + */ +FL_EXPORT char const * fl_get_combox_text(FL_OBJECT * ob); -inline -void Combox::setpost(FL_COMBO_PRE_POST cb) -{ - _post = cb; -} +/** \return the contents of \param line of the combox browser. */ +FL_EXPORT char const * fl_get_combox_line(FL_OBJECT * ob, int line); +/** \return the number of items in the combox browser. */ +FL_EXPORT int fl_get_combox_maxitems(FL_OBJECT * ob); -inline -int Combox::get() const -{ - return sel; -} +/** Show the browser */ +void fl_show_combox_browser(FL_OBJECT * ob); +/** Hide the browser */ +void fl_hide_combox_browser(FL_OBJECT * ob); -inline -string const Combox::getline() const -{ - if (type == FL_COMBOX_INPUT) - return fl_get_input(label); - else - return (browser && sel > 0) ? - string(fl_get_browser_line(browser, sel)) : string(); +#if defined(__cplusplus) } +#endif #endif diff --git a/src/frontends/xforms/forms/README b/src/frontends/xforms/forms/README index 6c5dac9687..553eed2697 100644 --- a/src/frontends/xforms/forms/README +++ b/src/frontends/xforms/forms/README @@ -41,9 +41,10 @@ Being more explicit: FL_TEXT | text The only exceptions to this are objects that are to be converted in the sed -scripts. At the moment this applies only to bmtable: +scripts. At the moment this applies only to bmtable and to combox: Convert an FL_BUTTON to a FL_BMTABLE by using prefix "bmtable". + Convert an FL_CHOICE to a FL_COMBOX by using prefix "combox". Enter the full name of the callback eg.: C_FormBaseOkCB diff --git a/src/frontends/xforms/forms/fdfix.sh b/src/frontends/xforms/forms/fdfix.sh index 7a8f3754b8..4c826186c0 100644 --- a/src/frontends/xforms/forms/fdfix.sh +++ b/src/frontends/xforms/forms/fdfix.sh @@ -140,9 +140,12 @@ INTRO_MESSAGE ${TMP} echo "#include " >> ${TMP} echo "#include \"forms_gettext.h\"" >> ${TMP} echo "#include \"gettext.h\"" >> ${TMP} +echo "#include FORMS_H_LOCATION" >> ${TMP} grep bmtable ${CIN} > /dev/null && echo "#include \"bmtable.h\"" >> ${TMP} +grep combox ${CIN} > /dev/null && + echo "#include \"combox.h\"" >> ${TMP} sed -f ${FDFIXC} < ${CIN} >> ${TMP} diff --git a/src/frontends/xforms/forms/fdfixc.sed b/src/frontends/xforms/forms/fdfixc.sed index 93b7722862..b2db372ac7 100644 --- a/src/frontends/xforms/forms/fdfixc.sed +++ b/src/frontends/xforms/forms/fdfixc.sed @@ -22,8 +22,8 @@ s/[ ]*$// /^\/\*-----/d -# Replace "forms.h" by FORMS_H_LOCATION in the #include directives -s/#include \"forms\.h\"/#include FORMS_H_LOCATION/ +# Remove '#include "forms.h"'. It is replace by a macro in fdfix.sh. +/^#include \"forms\.h\"/d # Pretty formatting; replace all leading whitespace with a tab @@ -74,6 +74,11 @@ s/\( fdui->form\)\(.*bgn_form.*\)/\1\2\ /bmtable/ s/fl_add_button/fl_add_bmtable/ +# For all lines containing "combox", +# replace "fl_add_choice" with "fl_add_combox" +/combox/ s/fl_add_choice([^,]*/fl_add_combox(FL_DROPLIST_COMBOX/ + + # For all lines containing fl_add_choice, # add a line that turns off the title. (These titles can contain meta-chars # that just look nasty ;-) diff --git a/src/frontends/xforms/forms/form_character.fd b/src/frontends/xforms/forms/form_character.fd index 03d81c45eb..63dee92a69 100644 --- a/src/frontends/xforms/forms/form_character.fd +++ b/src/frontends/xforms/forms/form_character.fd @@ -11,7 +11,7 @@ SnapGrid: 5 Name: form_character Width: 300 Height: 415 -Number of Objects: 15 +Number of Objects: 14 -------------------- class: FL_BOX @@ -126,37 +126,19 @@ class: FL_CHOICE type: DROPLIST_CHOICE box: 95 175 190 30 boxtype: FL_FRAME_BOX -colors: FL_COL1 FL_BLACK +colors: FL_COL1 FL_COL1 alignment: FL_ALIGN_LEFT style: FL_NORMAL_STYLE size: FL_NORMAL_SIZE lcol: FL_BLACK -label: Language: +label: Language:|#L shortcut: resize: FL_RESIZE_X gravity: FL_NorthWest FL_NorthEast -name: choice_language +name: combox_language callback: C_FormDialogView_InputCB argument: 0 --------------------- -class: FL_TEXT -type: NORMAL_TEXT -box: 11 170 84 40 -boxtype: FL_FLAT_BOX -colors: FL_COL1 FL_MCOL -alignment: FL_ALIGN_RIGHT|FL_ALIGN_INSIDE -style: FL_NORMAL_STYLE -size: FL_NORMAL_SIZE -lcol: FL_BLACK -label: Language: -shortcut: -resize: FL_RESIZE_ALL -gravity: FL_NoGravity FL_NoGravity -name: -callback: -argument: - -------------------- class: FL_CHECKBUTTON type: PUSH_BUTTON diff --git a/src/frontends/xforms/forms/form_document.fd b/src/frontends/xforms/forms/form_document.fd index 6b721417c6..e2f93c1b59 100644 --- a/src/frontends/xforms/forms/form_document.fd +++ b/src/frontends/xforms/forms/form_document.fd @@ -819,19 +819,19 @@ argument: 0 -------------------- class: FL_CHOICE -type: NORMAL_CHOICE +type: DROPLIST_CHOICE box: 110 10 160 25 boxtype: FL_FRAME_BOX -colors: FL_COL1 FL_BLACK +colors: FL_COL1 FL_COL1 alignment: FL_ALIGN_LEFT style: FL_NORMAL_STYLE size: FL_NORMAL_SIZE lcol: FL_BLACK -label: Class:|#l +label: Class:|#C shortcut: resize: FL_RESIZE_ALL gravity: FL_NoGravity FL_NoGravity -name: choice_doc_class +name: combox_doc_class callback: C_FormBaseInputCB argument: 0 @@ -1330,10 +1330,10 @@ argument: -------------------- class: FL_CHOICE -type: NORMAL_CHOICE +type: DROPLIST_CHOICE box: 120 35 190 25 boxtype: FL_FRAME_BOX -colors: FL_COL1 FL_BLACK +colors: FL_COL1 FL_COL1 alignment: FL_ALIGN_LEFT style: FL_NORMAL_STYLE size: FL_NORMAL_SIZE @@ -1342,7 +1342,7 @@ label: Language:|#L shortcut: resize: FL_RESIZE_ALL gravity: FL_NoGravity FL_NoGravity -name: choice_language +name: combox_language callback: C_FormBaseInputCB argument: 0 diff --git a/src/frontends/xforms/forms/form_preferences.fd b/src/frontends/xforms/forms/form_preferences.fd index ef0ce498f3..acde64cdd0 100644 --- a/src/frontends/xforms/forms/form_preferences.fd +++ b/src/frontends/xforms/forms/form_preferences.fd @@ -1605,7 +1605,7 @@ class: FL_CHOICE type: NORMAL_CHOICE box: 231 56 200 30 boxtype: FL_FRAME_BOX -colors: FL_COL1 FL_BLACK +colors: FL_COL1 FL_COL1 alignment: FL_ALIGN_LEFT style: FL_NORMAL_STYLE size: FL_DEFAULT_SIZE @@ -1614,7 +1614,7 @@ label: Default language:|#l shortcut: resize: FL_RESIZE_ALL gravity: FL_NoGravity FL_NoGravity -name: choice_default_lang +name: combox_default_lang callback: C_FormBaseInputCB argument: 0 diff --git a/src/frontends/xforms/freebrowser.c b/src/frontends/xforms/freebrowser.c new file mode 100644 index 0000000000..0ab13e7b36 --- /dev/null +++ b/src/frontends/xforms/freebrowser.c @@ -0,0 +1,228 @@ +/** + * \file freebrowser.c + * + * \author Alejandro Aguilar Sierra + * \author Angus Leeming + * + * This is a rewrite of Alejandro's C++ Combox class, originally written + * for LyX in 1996. The rewrite turns it into a native xforms widget. + */ +#include + +#include FORMS_H_LOCATION +#include "freebrowser.h" +#include /* isprint */ + +extern void fl_hide_tooltip(void); + +static void browser_cb(FL_OBJECT * ob, long data); + +static int peek_event(FL_FORM * form, void * xev); + + +FL_FREEBROWSER * fl_create_freebrowser(void * parent) +{ + FL_FORM * current_form = fl_current_form; + FL_FREEBROWSER * fb = fl_calloc(1, sizeof(FL_FREEBROWSER)); + FL_OBJECT * ob; + + /* Default size */ + FL_Coord const w = 100; + FL_Coord const h = 100; + + fb->parent = parent; + fb->callback = 0; + fb->want_printable = 0; + fb->last_printable = 0; + + if (current_form) fl_end_form(); + fb->form = fl_bgn_form(FL_NO_BOX, w, h); + + fb->form->u_vdata = fb; + fl_register_raw_callback(fb->form, ButtonPressMask|KeyPressMask, + peek_event); + + ob = fb->browser = fl_add_browser(FL_HOLD_BROWSER, 0, 0, w, h, ""); + ob->u_vdata = fb; + fl_set_object_boxtype(ob, FL_UP_BOX); + fl_set_object_color(ob, FL_MCOL, FL_YELLOW); + fl_set_object_gravity(ob, NorthWestGravity, SouthEastGravity); + fl_set_object_callback(ob, browser_cb, 0); + fl_end_form(); + + if (current_form) + fl_addto_form(current_form); + + return fb; +} + + +void fl_free_freebrowser(FL_FREEBROWSER * fb) +{ + if (!fb) + return; + + if (fb->form) + fl_free_form(fb->form); + + fl_free(fb); + fb = 0; +} + + +void fl_show_freebrowser(FL_FREEBROWSER * fb, + FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h) +{ + int tmp; + int const pos = fl_get_browser(fb->browser); + + fl_set_form_geometry(fb->form, x, y, w, h); + + XGetInputFocus(fl_get_display(), &fb->save_window, &tmp); + XFlush(fl_get_display()); + + fl_show_form(fb->form, FL_PLACE_POSITION, FL_NOBORDER, ""); + + fl_select_browser_line(fb->browser, pos); + fl_set_browser_topline(fb->browser, pos); + + XGrabPointer(fl_get_display(), fb->form->window, 0, + ButtonPressMask | ButtonReleaseMask | PointerMotionMask, + GrabModeAsync, GrabModeAsync, + 0, 0, 0); + XFlush(fl_get_display()); + + fl_hide_tooltip(); +} + + +void fl_hide_freebrowser(FL_FREEBROWSER * fb) +{ + XUngrabPointer(fl_get_display(), 0); + XFlush(fl_get_display()); + + if (fb->form->visible) + fl_hide_form(fb->form); + + XSetInputFocus(fl_get_display(), fb->save_window, + RevertToParent, CurrentTime); + XFlush(fl_get_display()); + + if (fb->callback) + fb->callback(fb, 0); +} + + +FL_OBJECT * fl_get_freebrowser_browser(FL_FREEBROWSER * fb) +{ + return fb->browser; +} + + +static void browser_cb(FL_OBJECT * ob, long data) +{ + FL_FREEBROWSER * fb = ob->u_vdata; + fl_hide_freebrowser(fb); + if (fb->callback) + fb->callback(fb, 1); +} + + +static int peek_event(FL_FORM * form, void * ev) +{ + XEvent * xev = ev; + FL_FREEBROWSER * fb = form->u_vdata; + FL_OBJECT * browser = fb->browser; + + fb->last_printable = 0; + fl_hide_tooltip(); + + if (xev->type == ButtonPress && + ((int)(xev->xbutton.x) - (int)(browser->x) < 0 || + (int)(xev->xbutton.x) - (int)(browser->x) > (int)(browser->w) || + (int)(xev->xbutton.y) - (int)(browser->y) < 0 || + (int)(xev->xbutton.y) - (int)(browser->y) > (int)(browser->h))) { + fl_hide_freebrowser(fb); + return 1; + } + + if (xev->type == KeyPress) { + char s_r[10]; s_r[9] = '\0'; + KeySym keysym_return; + XLookupString(&xev->xkey, s_r, 10, &keysym_return, 0); + + XFlush(fl_get_display()); + + switch (keysym_return) { + case XK_Down: +#ifdef XK_KP_Down + case XK_KP_Down: +#endif + { + int sel = fl_get_browser(browser); + int const top = fl_get_browser_topline(browser); + int const screenlines = fl_get_browser_screenlines(browser); + + if (sel < 1 || sel >= fl_get_browser_maxline(browser)) + return 0; + + ++sel; + fl_select_browser_line(browser, sel); + + if (sel >= top + screenlines) + fl_set_browser_topline(browser, sel - screenlines + 1); + + if (sel < top) + fl_set_browser_topline(browser, sel); + + return 1; + } + + case XK_Up: +#ifdef XK_KP_Up + case XK_KP_Up: +#endif + { + int sel = fl_get_browser(browser); + int const top = fl_get_browser_topline(browser); + int const screenlines = fl_get_browser_screenlines(browser); + + if (sel <= 1 || sel > fl_get_browser_maxline(browser)) + return 0; + + --sel; + fl_select_browser_line(browser, sel); + + if (sel >= top + screenlines) + fl_set_browser_topline(browser, sel - screenlines + 1); + + if (sel < top) + fl_set_browser_topline(browser, sel); + + return 1; + } + + case XK_Return: +#ifdef XK_KP_Enter + case XK_KP_Enter: +#endif + fl_hide_freebrowser(fb); + if (fb->callback) + fb->callback(fb, 1); + return 1; + + case XK_Escape: + fl_hide_freebrowser(fb); + return 1; + default: + if (fb->want_printable && s_r[0] && isprint(s_r[0])) { + fb->last_printable = s_r[0]; + fl_hide_freebrowser(fb); + if (fb->callback) + fb->callback(fb, 1); + return 1; + } + } + } + return 0; +} diff --git a/src/frontends/xforms/freebrowser.h b/src/frontends/xforms/freebrowser.h new file mode 100644 index 0000000000..a7d7a72753 --- /dev/null +++ b/src/frontends/xforms/freebrowser.h @@ -0,0 +1,68 @@ +/** + * \file freebrowser.h + * \author Angus Leeming + * + * A freebrowser is a browser widget in its own form. + * It is used for example to instantiate the drop-down list beneath a + * combox. + */ + +#ifndef FL_FREEBROWSER_H +#define FL_FREEBROWSER_H + +#if defined(__cplusplus) +extern "C" +{ +#endif + +enum freebrowser_position { + FL_FREEBROWSER_BELOW, + FL_FREEBROWSER_ABOVE +}; + +typedef struct fl_freebrowser_ { + /** Use this and you'll be told when something happens. + * \param == 0: the browser has merely been hidden. + * == 1: a change has been made. + */ + void (* callback) (struct fl_freebrowser_ *, int action); + + /** Set this to 1 if you want to capture all KeyPress events + * generating printable chars. + */ + int want_printable; + /** Is set only if want_printable is true. */ + char last_printable; + + /** Details of the implementation. */ + void * parent; + FL_FORM * form; + FL_OBJECT * browser; + Window save_window; +} FL_FREEBROWSER; + + +/** A function to create a freebrowser widget, "owned" by widget \param parent. + */ +FL_EXPORT FL_FREEBROWSER * fl_create_freebrowser(void * parent); + +FL_EXPORT void fl_free_freebrowser(FL_FREEBROWSER *); + +/** \param abs_x, \param abs_y are the coordinates of the top left corner + * of the browser relative to the top left hand corner of the _screen_. + * \param w, \param h are the browser dimensions. + */ +FL_EXPORT void fl_show_freebrowser(FL_FREEBROWSER *, + FL_Coord abs_x, FL_Coord abs_y, + FL_Coord w, FL_Coord h); + +FL_EXPORT void fl_hide_freebrowser(FL_FREEBROWSER *); + +/** Return the browser itself. */ +FL_EXPORT FL_OBJECT * fl_get_freebrowser_browser(FL_FREEBROWSER *); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/src/frontends/xforms/xforms_helpers.C b/src/frontends/xforms/xforms_helpers.C index aceff7a8da..1fe3d7bac3 100644 --- a/src/frontends/xforms/xforms_helpers.C +++ b/src/frontends/xforms/xforms_helpers.C @@ -26,6 +26,7 @@ #include #include FORMS_H_LOCATION +#include "combox.h" using std::ofstream; using std::pair; @@ -131,6 +132,10 @@ string const getString(FL_OBJECT * ob, int line) tmp = fl_get_choice_item_text(ob, line); break; + case FL_COMBOX: + tmp = fl_get_combox_text(ob); + break; + default: lyx::Assert(0); }