Mercurial > octave
changeset 21824:6780a8657be3
Implement uibuttongroup (bug #47513)
* doc/interpreter/genpropdoc.m: Wire in uibuttongroup documentation creation
* doc/interpreter/gui.txi: Add documentation node for uibuttongroup
* doc/interpreter/module.mk: Wire in uibuttongroup documentation creation
* doc/interpreter/plot.txi: Add documentation node for uibuttongroup
* libgui/graphics/__init_qt__.cc (__init__): Set default styling for uibuttongroup
* libgui/graphics/Backend.cc (toolkitObjectProperty): Add uibuttongroup
* libgui/graphics/Backend.cc (Backend::initialize): Add uibuttongroup
* libgui/graphics/Backend.cc (Backend::update): Add uibuttongroup
* libgui/graphics/ButtonControl.cc (ButtonControl::update): Catch forced uncheck of selected button in buttongroup
* libgui/graphics/Canvas.cc (Canvas::select_object): Allow uibuttongroup to be selected like uicontrol or uipanel
* libgui/graphics/Figure.cc (hasUiControlChildren): Ensure that uibuttongroup is known to have children
* libgui/graphics/module.mk: Wire in ButtonGroup
* libgui/graphics/ObjectFactory.cc (ObjectFactory::createObject): Create ButtonGroup for uibuttongroup
* libgui/graphics/QtHandlesUtils.cc (computeFont<uibuttongroup>): Make computeFont template for uibuttongroup
* libgui/graphics/RadioButtonControl.cc (RadioButtonControl::RadioButtonControl): On creation of button add to ButtonGroup
* libgui/graphics/ToggleButtonControl.cc (ToggleButtonControl::ToggleButtonControl): On creation of button add to ButtonGroup
* libinterp/corefcn/gl-render.cc (opengl_renderer::draw): Allow uibuttongroup to be drawn
* libinterp/corefcn/gl-render.cc (opengl_renderer::draw_uibuttongroup): Method to draw uibuttongroup
* libinterp/corefcn/gl-render.h (opengl_renderer::draw_uibuttongroup): Method to draw uibuttongroup
* libinterp/corefcn/graphics.cc (lookup_object_name): Wire in uibuttongroup
* libinterp/corefcn/graphics.cc (make_graphics_object_from_type): Wire in uibuttongroup
* libinterp/corefcn/graphics.cc (property_list::set): Wire in uibuttongroup
* libinterp/corefcn/graphics.cc (property_list::lookup): Wire in uibuttongroup
* libinterp/corefcn/graphics.cc (uibuttongroup::properties::get_boundingbox uibuttongroup::properties::set_units uibuttongroup::properties::update_units uibuttongroup::properties::set_fontunits uibuttongroup::properties::update_fontunits uibuttongroup::properties::get_fontsize_points uibuttongroup::properties::set_selectedobject): Add property methods for uibuttongroup
* libinterp/corefcn/graphics.in.h: Add uibuttongroup
* scripts/gui/module.mk: Wire in uibuttongroup script
* scripts/help/__unimplemented__.m: Remove uibuttongroup from unimplemented
* libgui/graphics/ButtonGroup.cc: Add QT toolkit ButtonGroup object
* libgui/graphics/ButtonGroup.h: Add QT toolkit ButtonGroup object
* scripts/gui/uibuttongroup.m: Create uibuttongroup script
author | Andrew Thornton <art27@cantab.net> |
---|---|
date | Thu, 05 May 2016 20:03:26 +0100 |
parents | 49d999dc443f |
children | f1f17f13b3b9 |
files | doc/interpreter/genpropdoc.m doc/interpreter/gui.txi doc/interpreter/module.mk doc/interpreter/plot.txi libgui/graphics/Backend.cc libgui/graphics/ButtonControl.cc libgui/graphics/ButtonGroup.cc libgui/graphics/ButtonGroup.h libgui/graphics/Canvas.cc libgui/graphics/Figure.cc libgui/graphics/ObjectFactory.cc libgui/graphics/QtHandlesUtils.cc libgui/graphics/RadioButtonControl.cc libgui/graphics/ToggleButtonControl.cc libgui/graphics/__init_qt__.cc libgui/graphics/module.mk libinterp/corefcn/gl-render.cc libinterp/corefcn/gl-render.h libinterp/corefcn/graphics.cc libinterp/corefcn/graphics.in.h scripts/gui/module.mk scripts/gui/uibuttongroup.m scripts/help/__unimplemented__.m |
diffstat | 23 files changed, 1064 insertions(+), 15 deletions(-) [+] |
line wrap: on
line diff
--- a/doc/interpreter/genpropdoc.m Fri Jun 03 20:56:33 2016 -0700 +++ b/doc/interpreter/genpropdoc.m Thu May 05 20:03:26 2016 +0100 @@ -31,7 +31,7 @@ function genpropdoc (objname, fname) objnames = {"root", "figure", "axes", "line", ... "text", "image", "patch", "surface", "light", ... - "uimenu", "uicontextmenu", "uipanel", ... + "uimenu", "uibuttongroup", "uicontextmenu", "uipanel", ... "uicontrol", "uitoolbar", "uipushtool", "uitoggletool"}; ## Base properties @@ -1374,6 +1374,33 @@ endswitch + ## uibuttongroup properties + elseif (strcmp (objname, "uibuttongroup")) + switch (field) + ## Overridden shared properties + + ## Specific properties + case "backgroundcolor" + case "bordertype" + case "borderwidth" + case "fontangle" + case "fontname" + case "fontsize" + case "fontunits" + case "fontweight" + case "foregroundcolor" + case "highlightcolor" + case "position" + case "resizefcn" + case "selectedobject" + case "selectionchangedfcn" + case "shadowcolor" + case "title" + case "titleposition" + case "units" + + endswitch + ## uicontrol properties elseif (strcmp (objname, "uicontrol")) switch (field)
--- a/doc/interpreter/gui.txi Fri Jun 03 20:56:33 2016 -0700 +++ b/doc/interpreter/gui.txi Thu May 05 20:03:26 2016 +0100 @@ -100,6 +100,8 @@ @DOCSTRING(uimenu) +@DOCSTRING(uibuttongroup) + @DOCSTRING(uicontextmenu) @DOCSTRING(uicontrol) @@ -149,4 +151,3 @@ @DOCSTRING(ispref) @DOCSTRING(preferences) -
--- a/doc/interpreter/module.mk Fri Jun 03 20:56:33 2016 -0700 +++ b/doc/interpreter/module.mk Thu May 05 20:03:26 2016 +0100 @@ -11,6 +11,7 @@ doc/interpreter/plot-surfaceproperties.texi \ doc/interpreter/plot-textproperties.texi \ doc/interpreter/plot-uimenuproperties.texi \ + doc/interpreter/plot-uibuttongroupproperties.texi \ doc/interpreter/plot-uicontextmenuproperties.texi \ doc/interpreter/plot-uipanelproperties.texi \ doc/interpreter/plot-uicontrolproperties.texi \ @@ -56,6 +57,9 @@ doc/interpreter/plot-uimenuproperties.texi: doc/interpreter/genpropdoc.m $(AM_V_GEN)$(call gen-propdoc-texi,uimenu) +doc/interpreter/plot-uibuttongroupproperties.texi: doc/interpreter/genpropdoc.m + $(AM_V_GEN)$(call gen-propdoc-texi,uibuttongroup) + doc/interpreter/plot-uicontextmenuproperties.texi: doc/interpreter/genpropdoc.m $(AM_V_GEN)$(call gen-propdoc-texi,uicontextmenu)
--- a/doc/interpreter/plot.txi Fri Jun 03 20:56:33 2016 -0700 +++ b/doc/interpreter/plot.txi Thu May 05 20:03:26 2016 +0100 @@ -1388,6 +1388,7 @@ * Surface Properties:: * Light Properties:: * Uimenu Properties:: +* Uibuttongroup Properties:: * Uicontextmenu Properties:: * Uipanel Properties:: * Uicontrol Properties:: @@ -1496,6 +1497,14 @@ @include plot-uimenuproperties.texi +@node Uibuttongroup Properties +@subsubsection Uibuttongroup Properties +@cindex uibuttongroup properties + +The @code{uibuttongroup} properties are: + +@include plot-uibuttongroupproperties.texi + @node Uicontextmenu Properties @subsubsection Uicontextmenu Properties @cindex uicontextmenu properties
--- a/libgui/graphics/Backend.cc Fri Jun 03 20:56:33 2016 -0700 +++ b/libgui/graphics/Backend.cc Thu May 05 20:03:26 2016 +0100 @@ -55,6 +55,7 @@ return std::string ("__plot_stream__"); else if (go.isa ("uicontrol") || go.isa ("uipanel") + || go.isa ("uibuttongroup") || go.isa ("uimenu") || go.isa ("uicontextmenu") || go.isa ("uitoolbar") @@ -87,6 +88,7 @@ if (go.isa ("figure") || go.isa ("uicontrol") || go.isa ("uipanel") + || go.isa ("uibuttongroup") || go.isa ("uimenu") || go.isa ("uicontextmenu") || go.isa ("uitoolbar") @@ -117,6 +119,7 @@ if (pId == figure::properties::ID___PLOT_STREAM__ || pId == uicontrol::properties::ID___OBJECT__ || pId == uipanel::properties::ID___OBJECT__ + || pId == uibuttongroup::properties::ID___OBJECT__ || pId == uimenu::properties::ID___OBJECT__ || pId == uicontextmenu::properties::ID___OBJECT__ || pId == uitoolbar::properties::ID___OBJECT__
--- a/libgui/graphics/ButtonControl.cc Fri Jun 03 20:56:33 2016 -0700 +++ b/libgui/graphics/ButtonControl.cc Thu May 05 20:03:26 2016 +0100 @@ -27,6 +27,7 @@ #include <QAbstractButton> #include "ButtonControl.h" +#include "ButtonGroup.h" #include "Container.h" #include "QtHandlesUtils.h" @@ -82,7 +83,16 @@ if (dValue != 0.0 && dValue != 1.0) warning ("button value not within valid display range"); else if (dValue == up.get_min () && btn->isChecked ()) - btn->setChecked (false); + { + btn->setChecked (false); + if (up.style_is ("radiobutton") || up.style_is ("togglebutton")) + { + Object* parent = Object::parentObject (gh_manager::get_object (up.get___myhandle__ ())); + ButtonGroup* btnGroup = dynamic_cast<ButtonGroup*>(parent); + if (btnGroup) + btnGroup->selectNothing (); + } + } else if (dValue == up.get_max () && ! btn->isChecked ()) btn->setChecked (true); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libgui/graphics/ButtonGroup.cc Thu May 05 20:03:26 2016 +0100 @@ -0,0 +1,487 @@ +/* + +Copyright (C) 2016 Andrew Thornton + +This file is part of Octave. + +Octave 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. + +Octave 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 Octave; see the file COPYING. If not, see +<http://www.gnu.org/licenses/>. + +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <QAbstractButton> +#include <QButtonGroup> +#include <QEvent> +#include <QFrame> +#include <QLabel> +#include <QMouseEvent> +#include <QRadioButton> +#include <QTimer> + +#include "Canvas.h" +#include "Container.h" +#include "ContextMenu.h" +#include "ButtonGroup.h" +#include "ToggleButtonControl.h" +#include "RadioButtonControl.h" +#include "Backend.h" +#include "QtHandlesUtils.h" + +#include "ov-struct.h" + +namespace QtHandles +{ + +static int +frameStyleFromProperties (const uibuttongroup::properties& pp) +{ + if (pp.bordertype_is ("none")) + return QFrame::NoFrame; + else if (pp.bordertype_is ("etchedin")) + return (QFrame::Box | QFrame::Sunken); + else if (pp.bordertype_is ("etchedout")) + return (QFrame::Box | QFrame::Raised); + else if (pp.bordertype_is ("beveledin")) + return (QFrame::Panel | QFrame::Sunken); + else if (pp.bordertype_is ("beveledout")) + return (QFrame::Panel | QFrame::Raised); + else + return (QFrame::Panel | QFrame::Plain); +} + +static void +setupPalette (const uibuttongroup::properties& pp, QPalette &p) +{ + p.setColor (QPalette::Window, + Utils::fromRgb (pp.get_backgroundcolor_rgb ())); + p.setColor (QPalette::WindowText, + Utils::fromRgb (pp.get_foregroundcolor_rgb ())); + p.setColor (QPalette::Light, + Utils::fromRgb (pp.get_highlightcolor_rgb ())); + p.setColor (QPalette::Dark, + Utils::fromRgb (pp.get_shadowcolor_rgb ())); +} + +static int +borderWidthFromProperties (const uibuttongroup::properties& pp) +{ + int bw = 0; + + if (! pp.bordertype_is ("none")) + { + bw = octave::math::round (pp.get_borderwidth ()); + if (pp.bordertype_is ("etchedin") || pp.bordertype_is ("etchedout")) + bw *= 2; + } + + return bw; +} + +ButtonGroup* +ButtonGroup::create (const graphics_object& go) +{ + Object* parent = Object::parentObject (go); + + if (parent) + { + Container* container = parent->innerContainer (); + + if (container) { + QFrame* frame = new QFrame(container); + return new ButtonGroup (go, new QButtonGroup (frame), frame); + } + } + + return 0; +} + +ButtonGroup::ButtonGroup (const graphics_object& go, QButtonGroup* buttongroup, QFrame* frame) + : Object (go, frame), m_hiddenbutton(0), m_container (0), m_title (0), m_blockUpdates (false) +{ + uibuttongroup::properties& pp = properties<uibuttongroup> (); + + frame->setObjectName ("UIButtonGroup"); + frame->setAutoFillBackground (true); + Matrix bb = pp.get_boundingbox (false); + frame->setGeometry (octave::math::round (bb(0)), octave::math::round (bb(1)), + octave::math::round (bb(2)), octave::math::round (bb(3))); + frame->setFrameStyle (frameStyleFromProperties (pp)); + frame->setLineWidth (octave::math::round (pp.get_borderwidth ())); + QPalette pal = frame->palette (); + setupPalette (pp, pal); + frame->setPalette (pal); + m_buttongroup = buttongroup; + m_hiddenbutton = new QRadioButton (frame); + m_hiddenbutton->hide (); + m_buttongroup->addButton (m_hiddenbutton); + + m_container = new Container (frame); + m_container->canvas (m_handle); + + if (frame->hasMouseTracking ()) + { + foreach (QWidget* w, frame->findChildren<QWidget*> ()) + { w->setMouseTracking (true); } + foreach (QWidget* w, buttongroup->findChildren<QWidget*> ()) + { w->setMouseTracking (true); } + } + + QString title = Utils::fromStdString (pp.get_title ()); + if (! title.isEmpty ()) + { + m_title = new QLabel (title, frame); + m_title->setAutoFillBackground (true); + m_title->setContentsMargins (4, 0, 4, 0); + m_title->setPalette (pal); + m_title->setFont (Utils::computeFont<uibuttongroup> (pp, bb(3))); + } + + frame->installEventFilter (this); + m_container->installEventFilter (this); + + if (pp.is_visible ()) + { + QTimer::singleShot (0, frame, SLOT (show (void))); + QTimer::singleShot (0, buttongroup, SLOT (show (void))); + } + else + frame->hide (); + + connect (m_buttongroup, SIGNAL (buttonClicked (QAbstractButton*)), SLOT (buttonClicked (QAbstractButton*))); +} + +ButtonGroup::~ButtonGroup (void) +{ +} + +bool +ButtonGroup::eventFilter (QObject* watched, QEvent* xevent) +{ + if (! m_blockUpdates) + { + if (watched == qObject ()) + { + switch (xevent->type ()) + { + case QEvent::Resize: + { + gh_manager::auto_lock lock; + graphics_object go = object (); + + if (go.valid_object ()) + { + if (m_title) + { + const uibuttongroup::properties& pp = + Utils::properties<uibuttongroup> (go); + + if (pp.fontunits_is ("normalized")) + { + QFrame* frame = qWidget<QFrame> (); + + m_title->setFont (Utils::computeFont<uibuttongroup> + (pp, frame->height ())); + m_title->resize (m_title->sizeHint ()); + } + } + updateLayout (); + } + } + break; + + case QEvent::MouseButtonPress: + { + QMouseEvent* m = dynamic_cast<QMouseEvent*> (xevent); + + if (m->button () == Qt::RightButton) + { + gh_manager::auto_lock lock; + + ContextMenu::executeAt (properties (), m->globalPos ()); + } + } + break; + + default: + break; + } + } + else if (watched == m_container) + { + switch (xevent->type ()) + { + case QEvent::Resize: + if (qWidget<QWidget> ()->isVisible ()) + { + gh_manager::auto_lock lock; + + properties ().update_boundingbox (); + } + break; + + default: + break; + } + } + } + + return false; +} + +void +ButtonGroup::update (int pId) +{ + uibuttongroup::properties& pp = properties<uibuttongroup> (); + QFrame* frame = qWidget<QFrame> (); + + m_blockUpdates = true; + + switch (pId) + { + case uibuttongroup::properties::ID_POSITION: + { + Matrix bb = pp.get_boundingbox (false); + + frame->setGeometry (octave::math::round (bb(0)), octave::math::round (bb(1)), + octave::math::round (bb(2)), octave::math::round (bb(3))); + updateLayout (); + } + break; + + case uibuttongroup::properties::ID_BORDERWIDTH: + frame->setLineWidth (octave::math::round (pp.get_borderwidth ())); + updateLayout (); + break; + + case uibuttongroup::properties::ID_BACKGROUNDCOLOR: + case uibuttongroup::properties::ID_FOREGROUNDCOLOR: + case uibuttongroup::properties::ID_HIGHLIGHTCOLOR: + case uibuttongroup::properties::ID_SHADOWCOLOR: + { + QPalette pal = frame->palette (); + + setupPalette (pp, pal); + frame->setPalette (pal); + if (m_title) + m_title->setPalette (pal); + } + break; + + case uibuttongroup::properties::ID_TITLE: + { + QString title = Utils::fromStdString (pp.get_title ()); + + if (title.isEmpty ()) + { + if (m_title) + delete m_title; + m_title = 0; + } + else + { + if (! m_title) + { + QPalette pal = frame->palette (); + + m_title = new QLabel (title, frame); + m_title->setAutoFillBackground (true); + m_title->setContentsMargins (4, 0, 4, 0); + m_title->setPalette (pal); + m_title->setFont (Utils::computeFont<uibuttongroup> (pp)); + m_title->show (); + } + else + { + m_title->setText (title); + m_title->resize (m_title->sizeHint ()); + } + } + updateLayout (); + } + break; + + case uibuttongroup::properties::ID_TITLEPOSITION: + updateLayout (); + break; + + case uibuttongroup::properties::ID_BORDERTYPE: + frame->setFrameStyle (frameStyleFromProperties (pp)); + updateLayout (); + break; + + case uibuttongroup::properties::ID_FONTNAME: + case uibuttongroup::properties::ID_FONTSIZE: + case uibuttongroup::properties::ID_FONTWEIGHT: + case uibuttongroup::properties::ID_FONTANGLE: + if (m_title) + { + m_title->setFont (Utils::computeFont<uibuttongroup> (pp)); + m_title->resize (m_title->sizeHint ()); + updateLayout (); + } + break; + + case uibuttongroup::properties::ID_VISIBLE: + frame->setVisible (pp.is_visible ()); + updateLayout (); + break; + + case uibuttongroup::properties::ID_SELECTEDOBJECT: + { + graphics_handle h = pp.get_selectedobject (); + gh_manager::auto_lock lock; + graphics_object go = gh_manager::get_object (h); + Object* selectedObject = Backend::toolkitObject (go); + ToggleButtonControl* toggle = static_cast<ToggleButtonControl*> (selectedObject); + RadioButtonControl* radio = static_cast<RadioButtonControl*>(selectedObject); + if (toggle) + { + go.get_properties ().set ("value", 1); + } + else if (radio) + { + go.get_properties ().set ("value", 1); + } + else + { + m_hiddenbutton->setChecked (true); + } + } + break; + + default: + break; + } + + m_blockUpdates = false; +} + +void +ButtonGroup::redraw (void) +{ + Canvas* canvas = m_container->canvas (m_handle); + + if (canvas) + canvas->redraw (); +} + +void +ButtonGroup::updateLayout (void) +{ + uibuttongroup::properties& pp = properties<uibuttongroup> (); + QFrame* frame = qWidget<QFrame> (); + + Matrix bb = pp.get_boundingbox (true); + int bw = borderWidthFromProperties (pp); + + frame->setFrameRect (QRect (octave::math::round (bb(0)) - bw, octave::math::round (bb(1)) - bw, + octave::math::round (bb(2)) + 2*bw, octave::math::round (bb(3)) + 2*bw)); + m_container->setGeometry (octave::math::round (bb(0)), octave::math::round (bb(1)), + octave::math::round (bb(2)), octave::math::round (bb(3))); + + if (m_blockUpdates) + pp.update_boundingbox (); + + if (m_title) + { + QSize sz = m_title->sizeHint (); + int offset = 5; + + if (pp.titleposition_is ("lefttop")) + m_title->move (bw+offset, 0); + else if (pp.titleposition_is ("righttop")) + m_title->move (frame->width () - bw - offset - sz.width (), 0); + else if (pp.titleposition_is ("leftbottom")) + m_title->move (bw+offset, frame->height () - sz.height ()); + else if (pp.titleposition_is ("rightbottom")) + m_title->move (frame->width () - bw - offset - sz.width (), + frame->height () - sz.height ()); + else if (pp.titleposition_is ("centertop")) + m_title->move (frame->width () / 2 - sz.width () / 2, 0); + else if (pp.titleposition_is ("centerbottom")) + m_title->move (frame->width () / 2 - sz.width () / 2, + frame->height () - sz.height ()); + } +} + +void +ButtonGroup::selectNothing (void) +{ + m_hiddenbutton->setChecked (true); +} + + +void +ButtonGroup::addButton (QAbstractButton* btn) +{ + m_buttongroup->addButton(btn); + connect (btn, SIGNAL (toggled (bool)), SLOT (buttonToggled (bool))); +} + +void +ButtonGroup::buttonToggled (bool toggled) +{ + Q_UNUSED (toggled); + if (!m_blockUpdates) + { + gh_manager::auto_lock lock; + uibuttongroup::properties& bp = properties<uibuttongroup> (); + + graphics_handle oldValue = bp.get_selectedobject(); + + QAbstractButton* checkedBtn = m_buttongroup->checkedButton(); + + graphics_handle newValue = graphics_handle (); + if (checkedBtn != m_hiddenbutton) + { + Object* checkedObj = Object::fromQObject(checkedBtn); + newValue = checkedObj->properties ().get___myhandle__ (); + } + + if (oldValue != newValue) + gh_manager::post_set (m_handle, "selectedobject", newValue.as_octave_value (), false); + } +} + +void +ButtonGroup::buttonClicked (QAbstractButton* btn) +{ + Q_UNUSED(btn); + + gh_manager::auto_lock lock; + uibuttongroup::properties& bp = properties<uibuttongroup> (); + + graphics_handle oldValue = bp.get_selectedobject(); + + QAbstractButton* checkedBtn = m_buttongroup->checkedButton(); + Object* checkedObj = Object::fromQObject(checkedBtn); + graphics_handle newValue = checkedObj->properties ().get___myhandle__ (); + + if (oldValue != newValue) + { + octave_scalar_map eventData; + eventData.setfield ("OldValue", oldValue.as_octave_value ()); + eventData.setfield ("NewValue", newValue.as_octave_value ()); + eventData.setfield ("Source", bp.get___myhandle__ ().as_octave_value ()); + eventData.setfield ("EventName", "SelectionChanged"); + octave_value selectionChangedEventObject = octave_value (new octave_struct (eventData)); + gh_manager::post_callback(m_handle, "selectionchangedfcn", selectionChangedEventObject); + } +} + +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libgui/graphics/ButtonGroup.h Thu May 05 20:03:26 2016 +0100 @@ -0,0 +1,78 @@ +/* + +Copyright (C) 2016 Andrew Thornton + +This file is part of Octave. + +Octave 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. + +Octave 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 Octave; see the file COPYING. If not, see +<http://www.gnu.org/licenses/>. + +*/ + +#if ! defined (octave_ButtonGroup_h) +#define octave_ButtonGroup_h 1 + +#include "Object.h" + +class QAbstractButton; +class QButtonGroup; +class QFrame; +class QLabel; +class QRadioButton; + +namespace QtHandles +{ + +class Container; + +class ButtonGroup : public Object +{ + Q_OBJECT + +public: + ButtonGroup (const graphics_object& go, QButtonGroup* buttongroup, QFrame* frame); + ~ButtonGroup (void); + + Container* innerContainer (void) { return m_container; } + + bool eventFilter (QObject* watched, QEvent* event); + + static ButtonGroup* create (const graphics_object& go); + + void addButton (QAbstractButton* btn); + + void selectNothing (void); + +protected: + void update (int pId); + void redraw (void); + +private slots: + void buttonToggled (bool toggled); + void buttonClicked (QAbstractButton* btn); + +private: + void updateLayout (void); + +private: + QButtonGroup* m_buttongroup; + QRadioButton* m_hiddenbutton; + Container* m_container; + QLabel* m_title; + bool m_blockUpdates; +}; + +}; // namespace QtHandles + +#endif
--- a/libgui/graphics/Canvas.cc Fri Jun 03 20:56:33 2016 -0700 +++ b/libgui/graphics/Canvas.cc Thu May 05 20:03:26 2016 +0100 @@ -386,7 +386,8 @@ if (childObj.isa ("axes")) axesList.append (childObj); - else if (childObj.isa ("uicontrol") || childObj.isa ("uipanel")) + else if (childObj.isa ("uicontrol") || childObj.isa ("uipanel") + || childObj.isa ("uibuttongroup")) { Matrix bb = childObj.get_properties ().get_boundingbox (false); QRectF r (bb(0), bb(1), bb(2), bb(3));
--- a/libgui/graphics/Figure.cc Fri Jun 03 20:56:33 2016 -0700 +++ b/libgui/graphics/Figure.cc Thu May 05 20:03:26 2016 +0100 @@ -371,12 +371,14 @@ } foreach (QFrame* frame, - qWidget<QWidget> ()->findChildren<QFrame*> ("UIPanel")) + qWidget<QWidget> ()->findChildren<QFrame*> ()) { - Object* obj = Object::fromQObject (frame); + if (frame->objectName () == "UIPanel" || frame->objectName () == "UIButtonGroup") { + Object* obj = Object::fromQObject (frame); - if (obj) - obj->slotRedraw (); + if (obj) + obj->slotRedraw (); + } } updateFigureToolBarAndMenuBar ();
--- a/libgui/graphics/ObjectFactory.cc Fri Jun 03 20:56:33 2016 -0700 +++ b/libgui/graphics/ObjectFactory.cc Thu May 05 20:03:26 2016 +0100 @@ -30,6 +30,7 @@ #include "graphics.h" #include "Backend.h" +#include "ButtonGroup.h" #include "CheckBoxControl.h" #include "ContextMenu.h" #include "EditControl.h" @@ -119,6 +120,8 @@ else if (up.style_is ("listbox")) obj = ListBoxControl::create (go); } + else if (go.isa ("uibuttongroup")) + obj = ButtonGroup::create (go); else if (go.isa ("uipanel")) obj = Panel::create (go); else if (go.isa ("uimenu"))
--- a/libgui/graphics/QtHandlesUtils.cc Fri Jun 03 20:56:33 2016 -0700 +++ b/libgui/graphics/QtHandlesUtils.cc Thu May 05 20:03:26 2016 +0100 @@ -135,6 +135,8 @@ template QFont computeFont<uipanel> (const uipanel::properties& props, int height); +template QFont computeFont<uibuttongroup> (const uibuttongroup::properties& props, + int height); QColor fromRgb (const Matrix& rgb) {
--- a/libgui/graphics/RadioButtonControl.cc Fri Jun 03 20:56:33 2016 -0700 +++ b/libgui/graphics/RadioButtonControl.cc Thu May 05 20:03:26 2016 +0100 @@ -26,6 +26,7 @@ #include <QRadioButton> +#include "ButtonGroup.h" #include "RadioButtonControl.h" #include "Container.h" #include "QtHandlesUtils.h" @@ -53,6 +54,11 @@ QRadioButton* radio) : ButtonControl (go, radio) { + Object* parent = Object::parentObject (go); + ButtonGroup* btnGroup = dynamic_cast<ButtonGroup*>(parent); + if (btnGroup) + btnGroup->addButton (radio); + radio->setAutoFillBackground (true); radio->setAutoExclusive (false); }
--- a/libgui/graphics/ToggleButtonControl.cc Fri Jun 03 20:56:33 2016 -0700 +++ b/libgui/graphics/ToggleButtonControl.cc Thu May 05 20:03:26 2016 +0100 @@ -27,6 +27,7 @@ #include <QPushButton> #include "ToggleButtonControl.h" +#include "ButtonGroup.h" #include "Container.h" #include "QtHandlesUtils.h" @@ -53,6 +54,11 @@ QPushButton* btn) : ButtonControl (go, btn) { + Object* parent = Object::parentObject (go); + ButtonGroup* btnGroup = dynamic_cast<ButtonGroup*>(parent); + if (btnGroup) + btnGroup->addButton (btn); + btn->setCheckable (true); btn->setAutoFillBackground (true); }
--- a/libgui/graphics/__init_qt__.cc Fri Jun 03 20:56:33 2016 -0700 +++ b/libgui/graphics/__init_qt__.cc Thu May 05 20:03:26 2016 +0100 @@ -83,6 +83,15 @@ octave_value (Utils::toRgb (p.color (QPalette::Light)))); root.set ("defaultuipanelshadowcolor", octave_value (Utils::toRgb (p.color (QPalette::Dark)))); + root.set ("defaultuibuttongroupbackgroundcolor", + octave_value (Utils::toRgb (p.color (QPalette::Window)))); + root.set ("defaultuibuttongroupforegroundcolor", + octave_value (Utils::toRgb + (p.color (QPalette::WindowText)))); + root.set ("defaultuibuttongrouphighlightcolor", + octave_value (Utils::toRgb (p.color (QPalette::Light)))); + root.set ("defaultuibuttongroupshadowcolor", + octave_value (Utils::toRgb (p.color (QPalette::Dark)))); qtHandlesInitialized = true;
--- a/libgui/graphics/module.mk Fri Jun 03 20:56:33 2016 -0700 +++ b/libgui/graphics/module.mk Thu May 05 20:03:26 2016 +0100 @@ -4,6 +4,7 @@ libgui/graphics/moc-annotation-dialog.cc \ libgui/graphics/moc-Backend.cc \ libgui/graphics/moc-ButtonControl.cc \ + libgui/graphics/moc-ButtonGroup.cc \ libgui/graphics/moc-ContextMenu.cc \ libgui/graphics/moc-EditControl.cc \ libgui/graphics/moc-Figure.cc \ @@ -48,6 +49,7 @@ libgui/graphics/Backend.h \ libgui/graphics/BaseControl.h \ libgui/graphics/ButtonControl.h \ + libgui/graphics/ButtonGroup.h \ libgui/graphics/Canvas.h \ libgui/graphics/CheckBoxControl.h \ libgui/graphics/Container.h \ @@ -88,6 +90,7 @@ libgui/graphics/Backend.cc \ libgui/graphics/BaseControl.cc \ libgui/graphics/ButtonControl.cc \ + libgui/graphics/ButtonGroup.cc \ libgui/graphics/Canvas.cc \ libgui/graphics/CheckBoxControl.cc \ libgui/graphics/Container.cc \
--- a/libinterp/corefcn/gl-render.cc Fri Jun 03 20:56:33 2016 -0700 +++ b/libinterp/corefcn/gl-render.cc Thu May 05 20:03:26 2016 +0100 @@ -651,6 +651,11 @@ if (toplevel) draw_uipanel (dynamic_cast<const uipanel::properties&> (props), go); } + else if (go.isa ("uibuttongroup")) + { + if (toplevel) + draw_uibuttongroup (dynamic_cast<const uibuttongroup::properties&> (props), go); + } else { warning ("opengl_renderer: cannot render object of type '%s'", @@ -714,6 +719,24 @@ } void +opengl_renderer::draw_uibuttongroup (const uibuttongroup::properties& props, + const graphics_object& go) +{ + graphics_object fig = go.get_ancestor ("figure"); + const figure::properties& figProps = + dynamic_cast<const figure::properties&> (fig.get_properties ()); + + // Initialize OpenGL context + + init_gl_context (figProps.is___enhanced__ (), + props.get_backgroundcolor_rgb ()); + + // Draw children + + draw (props.get_all_children (), false); +} + +void opengl_renderer::init_gl_context (bool enhanced, const Matrix& c) { #if defined (HAVE_OPENGL)
--- a/libinterp/corefcn/gl-render.h Fri Jun 03 20:56:33 2016 -0700 +++ b/libinterp/corefcn/gl-render.h Thu May 05 20:03:26 2016 +0100 @@ -70,7 +70,8 @@ virtual void draw_image (const image::properties& props); virtual void draw_uipanel (const uipanel::properties& props, const graphics_object& go); - + virtual void draw_uibuttongroup (const uibuttongroup::properties& props, + const graphics_object& go); virtual void init_gl_context (bool enhanced, const Matrix& backgroundColor); virtual void setup_opengl_transformation (const axes::properties& props);
--- a/libinterp/corefcn/graphics.cc Fri Jun 03 20:56:33 2016 -0700 +++ b/libinterp/corefcn/graphics.cc Thu May 05 20:03:26 2016 +0100 @@ -1071,7 +1071,8 @@ { pfx = name.substr (0, 13); - if (pfx.compare ("uicontextmenu")) + if (pfx.compare ("uicontextmenu") || + pfx.compare ("uibuttongroup")) offset = 13; } } @@ -1123,6 +1124,8 @@ go = new uicontrol (h, p); else if (type.compare ("uipanel")) go = new uipanel (h, p); + else if (type.compare ("uibuttongroup")) + go = new uibuttongroup (h, p); else if (type.compare ("uicontextmenu")) go = new uicontextmenu (h, p); else if (type.compare ("uitoolbar")) @@ -1985,7 +1988,8 @@ { pfx = name.substr (0, 13); - if (pfx.compare ("uicontextmenu")) + if (pfx.compare ("uicontextmenu") + || pfx.compare ("uibuttongroup")) offset = 13; } } @@ -2026,6 +2030,8 @@ has_property = uimenu::properties::has_core_property (pname); else if (pfx == "uicontrol") has_property = uicontrol::properties::has_core_property (pname); + else if (pfx == "uibuttongroup") + has_property = uibuttongroup::properties::has_core_property (pname); else if (pfx == "uipanel") has_property = uipanel::properties::has_core_property (pname); else if (pfx == "uicontextmenu") @@ -2122,7 +2128,8 @@ { pfx = name.substr (0, 13); - if (pfx.compare ("uicontextmenu")) + if (pfx.compare ("uicontextmenu") + || pfx.compare ("uibuttongroup")) offset = 13; } } @@ -8820,6 +8827,176 @@ // --------------------------------------------------------------------- Matrix +uibuttongroup::properties::get_boundingbox (bool internal, + const Matrix& parent_pix_size) const +{ + Matrix pos = get_position ().matrix_value (); + Matrix parent_size (parent_pix_size); + + if (parent_size.is_empty ()) + { + graphics_object go = gh_manager::get_object (get_parent ()); + + parent_size = + go.get_properties ().get_boundingbox (true).extract_n (0, 2, 1, 2); + } + + pos = convert_position (pos, get_units (), "pixels", parent_size); + + pos(0)--; + pos(1)--; + pos(1) = parent_size(1) - pos(1) - pos(3); + + if (internal) + { + double outer_height = pos(3); + + pos(0) = pos(1) = 0; + + if (! bordertype_is ("none")) + { + double bw = get_borderwidth (); + double mul = 1.0; + + if (bordertype_is ("etchedin") || bordertype_is ("etchedout")) + mul = 2.0; + + pos(0) += mul * bw; + pos(1) += mul * bw; + pos(2) -= 2 * mul * bw; + pos(3) -= 2 * mul * bw; + } + + if (! get_title ().empty ()) + { + double fontsz = get_fontsize (); + + if (! fontunits_is ("pixels")) + { + double res = xget (0, "screenpixelsperinch").double_value (); + + if (fontunits_is ("points")) + fontsz *= (res / 72.0); + else if (fontunits_is ("inches")) + fontsz *= res; + else if (fontunits_is ("centimeters")) + fontsz *= (res / 2.54); + else if (fontunits_is ("normalized")) + fontsz *= outer_height; + } + + if (titleposition_is ("lefttop") || titleposition_is ("centertop") + || titleposition_is ("righttop")) + pos(1) += (fontsz / 2); + pos(3) -= (fontsz / 2); + } + } + + return pos; +} + +void +uibuttongroup::properties::set_units (const octave_value& val) +{ + caseless_str old_units = get_units (); + + if (units.set (val, true)) + { + update_units (old_units); + mark_modified (); + } +} + +void +uibuttongroup::properties::update_units (const caseless_str& old_units) +{ + Matrix pos = get_position ().matrix_value (); + + graphics_object parent_go = gh_manager::get_object (get_parent ()); + Matrix parent_bbox = parent_go.get_properties ().get_boundingbox (true); + Matrix parent_size = parent_bbox.extract_n (0, 2, 1, 2); + + pos = convert_position (pos, old_units, get_units (), parent_size); + set_position (pos); +} + +void +uibuttongroup::properties::set_fontunits (const octave_value& val) +{ + caseless_str old_fontunits = get_fontunits (); + + if (fontunits.set (val, true)) + { + update_fontunits (old_fontunits); + mark_modified (); + } +} + +void +uibuttongroup::properties::update_fontunits (const caseless_str& old_units) +{ + caseless_str new_units = get_fontunits (); + double parent_height = get_boundingbox (false).elem (3); + double fontsz = get_fontsize (); + + fontsz = convert_font_size (fontsz, old_units, new_units, parent_height); + + set_fontsize (octave_value (fontsz)); +} + +double +uibuttongroup::properties::get_fontsize_points (double box_pix_height) const +{ + double fontsz = get_fontsize (); + double parent_height = box_pix_height; + + if (fontunits_is ("normalized") && parent_height <= 0) + parent_height = get_boundingbox (false).elem (3); + + return convert_font_size (fontsz, get_fontunits (), "points", parent_height); +} + +void +uibuttongroup::properties::set_selectedobject (const octave_value& v) +{ + graphics_handle current_selectedobject = get_selectedobject(); + selectedobject = current_selectedobject; + if (v.is_empty ()) + { + if (current_selectedobject.ok ()) + { + selectedobject = graphics_handle (); + mark_modified (); + } + return; + } + + graphics_handle val (v); + if (val.ok ()) + { + graphics_object go (gh_manager::get_object (val)); + base_properties& gop = go.get_properties (); + + if (go.valid_object () + && gop.get_parent () == get___myhandle__ () + && go.isa ("uicontrol")) + { + uicontrol::properties& cop = dynamic_cast<uicontrol::properties&> (go.get_properties ()); + const caseless_str& style = cop.get_style (); + if (style.compare ("radiobutton") || style.compare ("togglebutton")) + { + selectedobject = val; + mark_modified (); + return; + } + } + } + err_set_invalid ("selectedobject"); +} + +// --------------------------------------------------------------------- + +Matrix uipanel::properties::get_boundingbox (bool internal, const Matrix& parent_pix_size) const { @@ -9539,6 +9716,7 @@ plist_map["hggroup"] = hggroup::properties::factory_defaults (); plist_map["uimenu"] = uimenu::properties::factory_defaults (); plist_map["uicontrol"] = uicontrol::properties::factory_defaults (); + plist_map["uibuttongroup"] = uibuttongroup::properties::factory_defaults (); plist_map["uipanel"] = uipanel::properties::factory_defaults (); plist_map["uicontextmenu"] = uicontextmenu::properties::factory_defaults (); plist_map["uitoolbar"] = uitoolbar::properties::factory_defaults (); @@ -10395,6 +10573,15 @@ GO_BODY (uicontrol); } +DEFUN (__go_uibuttongroup__, args, , + "-*- texinfo -*-\n\ +@deftypefn {} {} __go_uibuttongroup__ (@var{parent})\n\ +Undocumented internal function.\n\ +@end deftypefn") +{ + GO_BODY (uibuttongroup); +} + DEFUN (__go_uipanel__, args, , "-*- texinfo -*-\n\ @deftypefn {} {} __go_uipanel__ (@var{parent})\n\ @@ -11526,4 +11713,3 @@ return ovl (); } -
--- a/libinterp/corefcn/graphics.in.h Fri Jun 03 20:56:33 2016 -0700 +++ b/libinterp/corefcn/graphics.in.h Thu May 05 20:03:26 2016 +0100 @@ -5568,6 +5568,91 @@ // --------------------------------------------------------------------- +class OCTINTERP_API uibuttongroup : public base_graphics_object +{ +public: + class OCTINTERP_API properties : public base_properties + { + public: + Matrix get_boundingbox (bool internal = false, + const Matrix& parent_pix_size = Matrix ()) const; + + double get_fontsize_points (double box_pix_height = 0) const; + + // See the genprops.awk script for an explanation of the + // properties declarations. + // Programming note: Keep property list sorted if new ones are added. + + BEGIN_PROPERTIES (uibuttongroup) + any_property __object__ h , Matrix () + color_property backgroundcolor , color_values (1, 1, 1) + radio_property bordertype , "none|{etchedin}|etchedout|beveledin|beveledout|line" + double_property borderwidth , 1 + bool_property clipping , "on" + radio_property fontangle , "{normal}|italic|oblique" + string_property fontname , OCTAVE_DEFAULT_FONTNAME + double_property fontsize , 10 + radio_property fontunits S , "inches|centimeters|normalized|{points}|pixels" + radio_property fontweight , "light|{normal}|demi|bold" + color_property foregroundcolor , color_values (0, 0, 0) + color_property highlightcolor , color_values (1, 1, 1) + array_property position , default_panel_position () + callback_property resizefcn , Matrix () + handle_property selectedobject S , graphics_handle() + callback_property selectionchangedfcn , Matrix() + color_property shadowcolor , color_values (0, 0, 0) + callback_property sizechangedfcn , Matrix () + radio_property units S , "{normalized}|inches|centimeters|points|pixels|characters" + string_property title , "" + radio_property titleposition , "{lefttop}|centertop|righttop|leftbottom|centerbottom|rightbottom" + END_PROPERTIES + + protected: + void init (void) + { + position.add_constraint (dim_vector (1, 4)); + } + + // void update_text_extent (void); + // void update_string (void) { update_text_extent (); } + // void update_fontname (void) { update_text_extent (); } + // void update_fontsize (void) { update_text_extent (); } + // void update_fontangle (void) { update_text_extent (); } + // void update_fontweight (void) { update_text_extent (); } + + void update_units (const caseless_str& old_units); + void update_fontunits (const caseless_str& old_units); + + }; + +private: + properties xproperties; + +public: + uibuttongroup (const graphics_handle& mh, const graphics_handle& p) + : base_graphics_object (), xproperties (mh, p) + { } + + ~uibuttongroup (void) { } + + base_properties& get_properties (void) { return xproperties; } + + const base_properties& get_properties (void) const { return xproperties; } + + bool valid_object (void) const { return true; } + + bool has_readonly_property (const caseless_str& pname) const + { + bool retval = xproperties.has_readonly_property (pname); + if (! retval) + retval = base_properties::has_readonly_property (pname); + return retval; + } + +}; + +// --------------------------------------------------------------------- + class OCTINTERP_API uipanel : public base_graphics_object { public:
--- a/scripts/gui/module.mk Fri Jun 03 20:56:33 2016 -0700 +++ b/scripts/gui/module.mk Thu May 05 20:03:26 2016 +0100 @@ -21,6 +21,7 @@ scripts/gui/listdlg.m \ scripts/gui/msgbox.m \ scripts/gui/questdlg.m \ + scripts/gui/uibuttongroup.m \ scripts/gui/uicontextmenu.m \ scripts/gui/uicontrol.m \ scripts/gui/uigetdir.m \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/gui/uibuttongroup.m Thu May 05 20:03:26 2016 +0100 @@ -0,0 +1,104 @@ +## Copyright (C) 2016 Andrew Thornton +## +## This file is part of Octave. +## +## Octave 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. +## +## Octave 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 Octave; see the file COPYING. If not, see +## <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {} {@var{hui} =} uibuttongroup (@var{property}, @var{value}, @dots{}) +## @deftypefnx {} {@var{hui} =} uibuttongroup (@var{parent}, @var{property}, @var{value}, @dots{}) +## @deftypefnx {} {} uibuttongroup (@var{h}) +## +## Create a uibuttongroup object and return a handle to it. +## +## uibuttongroups are used to create group uicontrols. +## +## If @var{parent} is omitted then a uibuttongroup for the current figure is +## created. If no figure is available, a new figure is created first. +## +## If @var{parent} is given then a uibuttongroup relative to @var{parent} is +## created. +## +## Any provided property value pairs will override the default values of the +## created uibuttongroup object. +## +## Uibuttongroup properties are documented at @ref{Uibuttongroup Properties}. +## +## Examples: +## +## @example +## @group +## % create figure and panel on it +## f = figure; +## % create a button group +## gp = uibuttongroup (f, "Position", [ 0 0.5 1 1]) +## % create a buttons in the group +## b1 = uicontrol (gp, "style", "radiobutton", ... +## "string", "Choice 1", ... +## "Position", [ 10 150 100 50 ]); +## b2 = uicontrol (gp, "style", "radiobutton", ... +## "string", "Choice 2", ... +## "Position", [ 10 50 100 30 ]); +## % create a button not in the group +## b3 = uicontrol (f, "style", "radiobutton", ... +## "string", "Not in the group", ... +## "Position", [ 10 50 100 50 ]); +## @end group +## @end example +## @seealso{figure, uipanel} +## @end deftypefn + +## Author: zeripath + +function hui = uibuttongroup (varargin) + + if (nargin == 1 && ishandle (varargin{1}) + && strcmpi (get (varargin{1}, "type"), "uibuttongroup")) + error ("uibuttongroup: focusing not implemented yet"); + endif + + [h, args] = __uiobject_split_args__ ("uibuttongroup", varargin, + {"figure", "uipanel", "uibuttongroup"}); + hui = __go_uibuttongroup__ (h, args{:}); + +endfunction + +%!demo +%! f = figure; +%! gp = uibuttongroup (f, "Position", [ 0 0.5 1 1], ... +%! "selectionchangedfcn", ... +%! @(x, y) display (['Selection Changed: ' get(y.NewValue, 'String')])); +%! b1 = uicontrol (gp, "style", "radiobutton", ... +%! "string", "Choice 1", ... +%! "Position", [ 10 150 100 50 ]); +%! b2 = uicontrol (gp, "style", "radiobutton", ... +%! "string", "Choice 2", ... +%! "Position", [ 10 50 100 30 ]); +%! b3 = uicontrol (f, "style", "radiobutton", ... +%! "string", "Not in the group", ... +%! "Position", [ 10 50 100 50 ]); +%! disp (['Current selected: ' get(get(gp, 'selectedobject'), 'String')]); +%! pause (0.5); +%! disp (['Select None']); +%! set (gp, 'selectedobject', []); +%! pause (0.1); +%! disp (['Current selected: ' get(get(gp, 'selectedobject'), 'String')]); +%! pause (0.5); +%! disp (['Select b1']); +%! set (gp, 'selectedobject', b1); +%! disp (['Current selected: ' get(get(gp, 'selectedobject'), 'String')]); + +## Uncertain if tests can be performed +%!assert (1)
--- a/scripts/help/__unimplemented__.m Fri Jun 03 20:56:33 2016 -0700 +++ b/scripts/help/__unimplemented__.m Thu May 05 20:03:26 2016 +0100 @@ -845,7 +845,6 @@ "toolboxdir", "triangulation", "tscollection", - "uibuttongroup", "uigetpref", "uiimport", "uiopen", @@ -900,4 +899,3 @@ %! assert (str(1:51), "quad2d is not implemented. Consider using dblquad."); %! str = __unimplemented__ ("MException"); %! assert (str(1:58), "the 'MException' function is not yet implemented in Octave"); -