GNU Octave  6.2.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
Panel.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2011-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29 
30 #include <QEvent>
31 #include <QFrame>
32 #include <QLabel>
33 #include <QMouseEvent>
34 #include <QTimer>
35 
36 #include "Canvas.h"
37 #include "Container.h"
38 #include "ContextMenu.h"
39 #include "Panel.h"
40 #include "QtHandlesUtils.h"
41 
42 #include "octave-qobject.h"
43 
44 #include "graphics.h"
45 #include "interpreter.h"
46 
47 namespace QtHandles
48 {
49 
50  static int
52  {
53  if (pp.bordertype_is ("none"))
54  return QFrame::NoFrame;
55  else if (pp.bordertype_is ("etchedin"))
56  return (QFrame::Box | QFrame::Sunken);
57  else if (pp.bordertype_is ("etchedout"))
58  return (QFrame::Box | QFrame::Raised);
59  else if (pp.bordertype_is ("beveledin"))
60  return (QFrame::Panel | QFrame::Sunken);
61  else if (pp.bordertype_is ("beveledout"))
62  return (QFrame::Panel | QFrame::Raised);
63  else
64  return (QFrame::Panel | QFrame::Plain);
65  }
66 
67  static void
68  setupPalette (const uipanel::properties& pp, QPalette& p)
69  {
70  p.setColor (QPalette::Window,
71  Utils::fromRgb (pp.get_backgroundcolor_rgb ()));
72  p.setColor (QPalette::WindowText,
73  Utils::fromRgb (pp.get_foregroundcolor_rgb ()));
74  p.setColor (QPalette::Light,
75  Utils::fromRgb (pp.get_highlightcolor_rgb ()));
76  p.setColor (QPalette::Dark,
77  Utils::fromRgb (pp.get_shadowcolor_rgb ()));
78  }
79 
80  static int
82  {
83  int bw = 0;
84 
85  if (! pp.bordertype_is ("none"))
86  {
87  bw = octave::math::round (pp.get_borderwidth ());
88  if (pp.bordertype_is ("etchedin") || pp.bordertype_is ("etchedout"))
89  bw *= 2;
90  }
91 
92  return bw;
93  }
94 
95  Panel*
97  const graphics_object& go)
98  {
99  Object *parent = parentObject (interp, go);
100 
101  if (parent)
102  {
103  Container *container = parent->innerContainer ();
104 
105  if (container)
106  return new Panel (oct_qobj, interp, go, new QFrame (container));
107  }
108 
109  return nullptr;
110  }
111 
113  const graphics_object& go, QFrame *frame)
114  : Object (oct_qobj, interp, go, frame), m_container (nullptr),
115  m_title (nullptr), m_blockUpdates (false),
116  m_previous_bbox (Matrix (1, 4, 0))
117  {
118  uipanel::properties& pp = properties<uipanel> ();
119 
120  frame->setObjectName ("UIPanel");
121  frame->setAutoFillBackground (true);
122  Matrix bb = pp.get_boundingbox (false);
123  frame->setGeometry (octave::math::round (bb(0)), octave::math::round (bb(1)),
124  octave::math::round (bb(2)), octave::math::round (bb(3)));
125  frame->setFrameStyle (frameStyleFromProperties (pp));
126  frame->setLineWidth (octave::math::round (pp.get_borderwidth ()));
127  QPalette pal = frame->palette ();
128  setupPalette (pp, pal);
129  frame->setPalette (pal);
130 
131  m_container = new Container (frame, oct_qobj, interp);
133 
134  connect (m_container, SIGNAL (interpeter_event (const fcn_callback&)),
135  this, SIGNAL (interpeter_event (const fcn_callback&)));
136 
137  connect (m_container, SIGNAL (interpeter_event (const meth_callback&)),
138  this, SIGNAL (interpeter_event (const meth_callback&)));
139 
140  if (frame->hasMouseTracking ())
141  {
142  for (auto *w : frame->findChildren<QWidget*> ())
143  w->setMouseTracking (true);
144  }
145 
146  QString title = Utils::fromStdString (pp.get_title ());
147  if (! title.isEmpty ())
148  {
149  m_title = new QLabel (title, frame);
150  m_title->setAutoFillBackground (true);
151  m_title->setContentsMargins (4, 0, 4, 0);
152  m_title->setPalette (pal);
153  m_title->setFont (Utils::computeFont<uipanel> (pp, bb(3)));
154  }
155 
156  frame->installEventFilter (this);
157  m_container->installEventFilter (this);
158 
159  graphics_object fig (go.get_ancestor ("figure"));
160  if (! fig.get ("keypressfcn").isempty ())
162 
163  if (! fig.get ("keyreleasefcn").isempty ())
165 
166  if (pp.is_visible ())
167  QTimer::singleShot (0, frame, SLOT (show (void)));
168  else
169  frame->hide ();
170  }
171 
173  { }
174 
175  bool
176  Panel::eventFilter (QObject *watched, QEvent *xevent)
177  {
178  if (! m_blockUpdates)
179  {
181 
182  if (watched == qObject ())
183  {
184  switch (xevent->type ())
185  {
186  case QEvent::Resize:
187  {
188  octave::autolock guard (gh_mgr.graphics_lock ());
189 
190  graphics_object go = object ();
191 
192  if (go.valid_object ())
193  {
194  if (m_title)
195  {
196  const uipanel::properties& pp =
197  Utils::properties<uipanel> (go);
198 
199  if (pp.fontunits_is ("normalized"))
200  {
201  QFrame *frame = qWidget<QFrame> ();
202 
204  (pp, frame->height ()));
205  m_title->resize (m_title->sizeHint ());
206  }
207  }
208  updateLayout ();
209  }
210  }
211  break;
212 
213  case QEvent::MouseButtonPress:
214  {
215  QMouseEvent *m = dynamic_cast<QMouseEvent *> (xevent);
216 
217  if (m->button () == Qt::RightButton)
218  {
219  octave::autolock guard (gh_mgr.graphics_lock ());
220 
221  graphics_object go = object ();
222 
223  if (go.valid_object ())
225  go.get_properties (),
226  m->globalPos ());
227  }
228  }
229  break;
230 
231  default:
232  break;
233  }
234  }
235  else if (watched == m_container)
236  {
237  switch (xevent->type ())
238  {
239  case QEvent::Resize:
240  if (qWidget<QWidget> ()->isVisible ())
241  {
242  octave::autolock guard (gh_mgr.graphics_lock ());
243 
244  graphics_object go = object ();
245 
246  if (go.valid_object ())
248  }
249  break;
250 
251  default:
252  break;
253  }
254  }
255  }
256 
257  return false;
258  }
259 
260  void
261  Panel::update (int pId)
262  {
263  uipanel::properties& pp = properties<uipanel> ();
264  QFrame *frame = qWidget<QFrame> ();
265 
266  m_blockUpdates = true;
267 
268  switch (pId)
269  {
270  case uipanel::properties::ID_POSITION:
271  {
272  Matrix bb = pp.get_boundingbox (false);
273  if (m_previous_bbox(0) != bb(0) || m_previous_bbox(1) != bb(1)
274  || m_previous_bbox(2) != bb(2) || m_previous_bbox(3) != bb(3))
275  {
276  frame->setGeometry (octave::math::round (bb(0)),
277  octave::math::round (bb(1)),
278  octave::math::round (bb(2)),
279  octave::math::round (bb(3)));
280  updateLayout ();
281  }
282  m_previous_bbox = bb;
283  }
284  break;
285 
286  case uipanel::properties::ID_BORDERWIDTH:
287  frame->setLineWidth (octave::math::round (pp.get_borderwidth ()));
288  updateLayout ();
289  break;
290 
291  case uipanel::properties::ID_BACKGROUNDCOLOR:
292  case uipanel::properties::ID_FOREGROUNDCOLOR:
293  case uipanel::properties::ID_HIGHLIGHTCOLOR:
294  case uipanel::properties::ID_SHADOWCOLOR:
295  {
296  QPalette pal = frame->palette ();
297 
298  setupPalette (pp, pal);
299  frame->setPalette (pal);
300  if (m_title)
301  m_title->setPalette (pal);
302  }
303  break;
304 
305  case uipanel::properties::ID_TITLE:
306  {
307  QString title = Utils::fromStdString (pp.get_title ());
308 
309  if (title.isEmpty ())
310  {
311  if (m_title)
312  delete m_title;
313  m_title = nullptr;
314  }
315  else
316  {
317  if (! m_title)
318  {
319  QPalette pal = frame->palette ();
320 
321  m_title = new QLabel (title, frame);
322  m_title->setAutoFillBackground (true);
323  m_title->setContentsMargins (4, 0, 4, 0);
324  m_title->setPalette (pal);
325  m_title->setFont (Utils::computeFont<uipanel> (pp));
326  m_title->show ();
327  }
328  else
329  {
330  m_title->setText (title);
331  m_title->resize (m_title->sizeHint ());
332  }
333  }
334  updateLayout ();
335  }
336  break;
337 
338  case uipanel::properties::ID_TITLEPOSITION:
339  updateLayout ();
340  break;
341 
342  case uipanel::properties::ID_BORDERTYPE:
343  frame->setFrameStyle (frameStyleFromProperties (pp));
344  updateLayout ();
345  break;
346 
347  case uipanel::properties::ID_FONTNAME:
348  case uipanel::properties::ID_FONTSIZE:
349  case uipanel::properties::ID_FONTWEIGHT:
350  case uipanel::properties::ID_FONTANGLE:
351  if (m_title)
352  {
353  m_title->setFont (Utils::computeFont<uipanel> (pp));
354  m_title->resize (m_title->sizeHint ());
355  updateLayout ();
356  }
357  break;
358 
359  case uipanel::properties::ID_VISIBLE:
360  frame->setVisible (pp.is_visible ());
361  updateLayout ();
362  break;
363 
364  default:
365  break;
366  }
367 
368  m_blockUpdates = false;
369  }
370 
371  void
373  {
374  update (uipanel::properties::ID_POSITION);
375 
376  Canvas *canvas = m_container->canvas (m_handle);
377 
378  if (canvas)
379  canvas->redraw ();
380  }
381 
382  void
384  {
385  uipanel::properties& pp = properties<uipanel> ();
386  QFrame *frame = qWidget<QFrame> ();
387 
388  Matrix bb = pp.get_boundingbox (true);
389  int bw = borderWidthFromProperties (pp);
390 
391  frame->setFrameRect (QRect (octave::math::round (bb(0)) - bw,
392  octave::math::round (bb(1)) - bw,
393  octave::math::round (bb(2)) + 2*bw, octave::math::round (bb(3)) + 2*bw));
394  m_container->setGeometry (octave::math::round (bb(0)),
395  octave::math::round (bb(1)),
396  octave::math::round (bb(2)), octave::math::round (bb(3)));
397 
398  if (m_blockUpdates)
399  pp.update_boundingbox ();
400 
401  if (m_title)
402  {
403  QSize sz = m_title->sizeHint ();
404  int offset = 5;
405 
406  if (pp.titleposition_is ("lefttop"))
407  m_title->move (bw+offset, 0);
408  else if (pp.titleposition_is ("righttop"))
409  m_title->move (frame->width () - bw - offset - sz.width (), 0);
410  else if (pp.titleposition_is ("leftbottom"))
411  m_title->move (bw+offset, frame->height () - sz.height ());
412  else if (pp.titleposition_is ("rightbottom"))
413  m_title->move (frame->width () - bw - offset - sz.width (),
414  frame->height () - sz.height ());
415  else if (pp.titleposition_is ("centertop"))
416  m_title->move (frame->width () / 2 - sz.width () / 2, 0);
417  else if (pp.titleposition_is ("centerbottom"))
418  m_title->move (frame->width () / 2 - sz.width () / 2,
419  frame->height () - sz.height ());
420  }
421  }
422 
423  void
424  Panel::do_connections (const QObject *receiver, const QObject* /* emitter */)
425  {
426  Object::do_connections (receiver);
428  }
429 
430 };
Definition: dMatrix.h:42
void addEventMask(int m)
Definition: Canvas.h:75
void redraw(bool sync=false)
Definition: Canvas.cc:58
Canvas * canvas(const graphics_handle &handle, bool create=true)
Definition: Container.cc:56
static void executeAt(octave::interpreter &interp, const base_properties &props, const QPoint &pt)
Definition: ContextMenu.cc:123
graphics_object object(void) const
Definition: Object.cc:83
virtual Container * innerContainer(void)=0
virtual void do_connections(const QObject *receiver, const QObject *emitter=nullptr)
Definition: Object.cc:225
octave::interpreter & m_interpreter
Definition: Object.h:140
static Object * parentObject(octave::interpreter &interp, const graphics_object &go)
Definition: Object.cc:201
virtual void show(void)
Definition: Object.cc:183
graphics_handle m_handle
Definition: Object.h:157
virtual QObject * qObject(void)
Definition: Object.h:82
Matrix m_previous_bbox
Definition: Panel.h:74
void redraw(void)
Definition: Panel.cc:372
void do_connections(const QObject *receiver, const QObject *emitter=nullptr)
Definition: Panel.cc:424
void updateLayout(void)
Definition: Panel.cc:383
Panel(octave::base_qobject &oct_qobj, octave::interpreter &interp, const graphics_object &go, QFrame *frame)
Definition: Panel.cc:112
~Panel(void)
Definition: Panel.cc:172
Container * m_container
Definition: Panel.h:71
void update(int pId)
Definition: Panel.cc:261
QLabel * m_title
Definition: Panel.h:72
bool m_blockUpdates
Definition: Panel.h:73
bool eventFilter(QObject *watched, QEvent *event)
Definition: Panel.cc:176
static Panel * create(octave::base_qobject &oct_qobj, octave::interpreter &interp, const graphics_object &go)
Definition: Panel.cc:96
virtual void update_boundingbox(void)
Definition: graphics.cc:3526
octave::mutex graphics_lock(void)
Definition: graphics.in.h:6393
octave_value get(bool all=false) const
Definition: graphics.in.h:2746
graphics_object get_ancestor(const std::string &type) const
Definition: graphics.cc:3905
base_properties & get_properties(void)
Definition: graphics.in.h:2829
bool valid_object(void) const
Definition: graphics.in.h:2847
Base class for Octave interfaces that use Qt.
gh_manager & get_gh_manager(void)
Definition: interpreter.h:295
bool isempty(void) const
Definition: ov.h:557
Matrix get_boundingbox(bool internal=false, const Matrix &parent_pix_size=Matrix()) const
Definition: graphics.cc:11248
T octave_idx_type m
Definition: mx-inlines.cc:773
std::complex< double > w(std::complex< double > z, double relerr=0)
QColor fromRgb(const Matrix &rgb)
template QFont computeFont< uipanel >(const uipanel::properties &props, int height)
QString fromStdString(const std::string &s)
static int frameStyleFromProperties(const uibuttongroup::properties &pp)
Definition: ButtonGroup.cc:57
static void setupPalette(const uibuttongroup::properties &pp, QPalette &p)
Definition: ButtonGroup.cc:74
static int borderWidthFromProperties(const uibuttongroup::properties &pp)
Definition: ButtonGroup.cc:87
double round(double x)
Definition: lo-mappers.h:136
std::function< void(octave::interpreter &)> meth_callback
Definition: event-manager.h:47
std::function< void(void)> fcn_callback
Definition: event-manager.h:46