MythTV  master
Visible.cpp
Go to the documentation of this file.
1 /* Visible.cpp
2 
3  Copyright (C) David C. J. Matthews 2004 dm at prolingua.co.uk
4 
5  This program is free software; you can redistribute it and/or
6  modify it under the terms of the GNU General Public License
7  as published by the Free Software Foundation; either version 2
8  of the License, or (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
18  Or, point your browser to http://www.gnu.org/copyleft/gpl.html
19 
20 */
21 #include "compat.h"
22 
23 #include "Visible.h"
24 #include "Presentable.h"
25 #include "Ingredients.h"
26 #include "Root.h"
27 #include "BaseClasses.h"
28 #include "ParseNode.h"
29 #include "ASN1Codes.h"
30 #include "Engine.h"
31 #include "Logging.h"
32 #include "freemheg.h"
33 
34 
35 // Copy constructor for cloning
37 {
44  m_nPosX = ref.m_nPosX;
45  m_nPosY = ref.m_nPosY;
47 }
48 
49 
51 {
53  // Original box size - two integer arguments.
54  MHParseNode *pOriginalBox = p->GetNamedArg(C_ORIGINAL_BOX_SIZE);
55 
56  if (! pOriginalBox)
57  {
58  MHParseNode::Failure("OriginalBoxSize missing");
59  }
60  else
61  {
62  m_nOriginalBoxWidth = pOriginalBox->GetArgN(0)->GetIntValue();
63  m_nOriginalBoxHeight = pOriginalBox->GetArgN(1)->GetIntValue();
64  }
65 
66  // Original position - two integer arguments. Optional
67  MHParseNode *pOriginalPos = p->GetNamedArg(C_ORIGINAL_POSITION);
68 
69  if (pOriginalPos)
70  {
71  m_nOriginalPosX = pOriginalPos->GetArgN(0)->GetIntValue();
72  m_nOriginalPosY = pOriginalPos->GetArgN(1)->GetIntValue();
73  }
74 
75  // OriginalPalette ref - optional.
76  MHParseNode *pOriginalPaletteRef = p->GetNamedArg(C_ORIGINAL_PALETTE_REF);
77 
78  if (pOriginalPaletteRef)
79  {
80  m_OriginalPaletteRef.Initialise(pOriginalPaletteRef->GetArgN(0), engine);
81  }
82 }
83 
84 void MHVisible::PrintMe(FILE *fd, int nTabs) const
85 {
86  MHPresentable::PrintMe(fd, nTabs);
87  PrintTabs(fd, nTabs);
88  fprintf(fd, ":OrigBoxSize %d %d\n", m_nOriginalBoxWidth, m_nOriginalBoxHeight);
89 
90  if (m_nOriginalPosX != 0 || m_nOriginalPosY != 0)
91  {
92  PrintTabs(fd, nTabs);
93  fprintf(fd, ":OrigPosition %d %d\n", m_nOriginalPosX, m_nOriginalPosY);
94  }
95 
97  {
98  PrintTabs(fd, nTabs);
99  fprintf(fd, ":OrigPaletteRef");
100  m_OriginalPaletteRef.PrintMe(fd, nTabs + 1);
101  fprintf(fd, "\n");
102  }
103 }
104 
106 {
107  if (m_fAvailable)
108  {
109  return; // Already prepared
110  }
111 
117  // Add a reference to this to the display stack.
118  engine->AddToDisplayStack(this);
120 }
121 
123 {
124  engine->RemoveFromDisplayStack(this);
126 }
127 
129 {
130  if (m_fRunning)
131  {
132  return;
133  }
134 
135  MHIngredient::Activation(engine);
136  m_fRunning = true;
137  engine->Redraw(GetVisibleArea()); // Display the visible.
138  engine->EventTriggered(this, EventIsRunning);
139 }
140 
142 {
143  if (! m_fRunning)
144  {
145  return;
146  }
147 
148  // Stop displaying. We need to save the area before we turn off m_fRunning but
149  // only call Redraw once this is no longer visible so that the area beneath will be drawn.
150  QRegion region = GetVisibleArea();
152  engine->Redraw(region); // Draw underlying object.
153 }
154 
155 // Return the colour, looking up in the palette if necessary. Used by the sub-classes
157 {
158  int red = 0;
159  int green = 0;
160  int blue = 0;
161  int alpha = 0;
162  if (colour.IsSet())
163  {
164  int cSize = colour.m_ColStr.Size();
165 
166  if (cSize != 4)
167  {
168  MHLOG(MHLogWarning, QString("Colour string has length %1 not 4.").arg(cSize));
169  }
170 
171  // Just in case the length is short we handle those properly.
172  if (cSize > 0)
173  {
174  red = colour.m_ColStr.GetAt(0);
175  }
176 
177  if (cSize > 1)
178  {
179  green = colour.m_ColStr.GetAt(1);
180  }
181 
182  if (cSize > 2)
183  {
184  blue = colour.m_ColStr.GetAt(2);
185  }
186 
187  if (cSize > 3)
188  {
189  alpha = 255 - colour.m_ColStr.GetAt(3); // Convert transparency to alpha
190  }
191  }
192 
193  return {red, green, blue, alpha};
194 }
195 
196 // Get the visible region of this visible. This is the area that needs to be drawn.
198 {
199  if (! m_fRunning)
200  {
201  return QRegion(); // Not visible at all.
202  }
203  return QRegion(QRect(m_nPosX, m_nPosY, m_nBoxWidth, m_nBoxHeight));
204 }
205 
206 // MHEG actions.
207 void MHVisible::SetPosition(int nXPosition, int nYPosition, MHEngine *engine)
208 {
209  // When we move a visible we have to redraw both the old area and the new.
210  // In some cases, such as moving an opaque rectangle we might be able to reduce
211  // this if there is some overlap.
212  QRegion drawRegion = GetVisibleArea();
213  m_nPosX = nXPosition;
214  m_nPosY = nYPosition;
215  drawRegion += GetVisibleArea();
216  engine->Redraw(drawRegion);
217 }
218 
219 void MHVisible::GetPosition(MHRoot *pXPosN, MHRoot *pYPosN)
220 {
221  pXPosN->SetVariableValue(m_nPosX);
222  pYPosN->SetVariableValue(m_nPosY);
223 }
224 
225 void MHVisible::SetBoxSize(int nWidth, int nHeight, MHEngine *engine)
226 {
227  QRegion drawRegion = GetVisibleArea();
228  m_nBoxWidth = nWidth;
229  m_nBoxHeight = nHeight;
230  drawRegion += GetVisibleArea();
231  engine->Redraw(drawRegion);
232 }
233 
234 void MHVisible::GetBoxSize(MHRoot *pWidthDest, MHRoot *pHeightDest)
235 {
236  pWidthDest->SetVariableValue(m_nBoxWidth);
237  pHeightDest->SetVariableValue(m_nBoxHeight);
238 }
239 
240 void MHVisible::SetPaletteRef(const MHObjectRef newPalette, MHEngine *engine)
241 {
242  m_PaletteRef.Copy(newPalette);
243  engine->Redraw(GetVisibleArea());
244 }
245 
247 {
248  engine->BringToFront(this);
249 }
250 
252 {
253  engine->SendToBack(this);
254 }
255 
256 void MHVisible::PutBefore(const MHRoot *pRef, MHEngine *engine)
257 {
258  engine->PutBefore(this, pRef);
259 }
260 
261 void MHVisible::PutBehind(const MHRoot *pRef, MHEngine *engine)
262 {
263  engine->PutBehind(this, pRef);
264 }
265 
266 // Copy constructor for cloning
268 {
275  m_LineStyle = ref.m_LineStyle;
276 }
277 
279 {
280  MHVisible::Initialise(p, engine);
281  // Bordered bounding box - optional
282  MHParseNode *pBBBox = p->GetNamedArg(C_BORDERED_BOUNDING_BOX);
283 
284  if (pBBBox)
285  {
286  m_fBorderedBBox = pBBBox->GetArgN(0)->GetBoolValue();
287  }
288 
289  // Original line width
290  MHParseNode *pOlw = p->GetNamedArg(C_ORIGINAL_LINE_WIDTH);
291 
292  if (pOlw)
293  {
295  }
296 
297  // Original line style. This is an integer not an enum.
298  MHParseNode *pOls = p->GetNamedArg(C_ORIGINAL_LINE_STYLE);
299 
300  if (pOls)
301  {
303  }
304 
305  // Line colour.
306  MHParseNode *pOrlc = p->GetNamedArg(C_ORIGINAL_REF_LINE_COLOUR);
307 
308  if (pOrlc)
309  {
310  m_OrigLineColour.Initialise(pOrlc->GetArgN(0), engine);
311  }
312 
313  // Fill colour
314  MHParseNode *pOrfc = p->GetNamedArg(C_ORIGINAL_REF_FILL_COLOUR);
315 
316  if (pOrfc)
317  {
318  m_OrigFillColour.Initialise(pOrfc->GetArgN(0), engine);
319  }
320 }
321 
322 void MHLineArt::PrintMe(FILE *fd, int nTabs) const
323 {
324  MHVisible::PrintMe(fd, nTabs);
325 
326  if (! m_fBorderedBBox)
327  {
328  PrintTabs(fd, nTabs);
329  fprintf(fd, ":BBBox false\n");
330  }
331 
332  if (m_nOriginalLineWidth != 1)
333  {
334  PrintTabs(fd, nTabs);
335  fprintf(fd, ":OrigLineWidth %d\n", m_nOriginalLineWidth);
336  }
337 
339  {
340  PrintTabs(fd, nTabs);
341  fprintf(fd, ":OrigLineStyle %d\n", m_OriginalLineStyle);
342  }
343 
344  if (m_OrigLineColour.IsSet())
345  {
346  PrintTabs(fd, nTabs);
347  fprintf(fd, ":OrigRefLineColour ");
348  m_OrigLineColour.PrintMe(fd, nTabs + 1);
349  fprintf(fd, "\n");
350  }
351 
352  if (m_OrigFillColour.IsSet())
353  {
354  PrintTabs(fd, nTabs);
355  fprintf(fd, ":OrigRefFillColour ");
356  m_OrigFillColour.PrintMe(fd, nTabs + 1);
357  fprintf(fd, "\n");
358  }
359 }
360 
362 {
363  if (m_fAvailable)
364  {
365  return; // Already prepared
366  }
367 
368  // Set up the internal attributes.
371 
372  if (m_OrigLineColour.IsSet())
373  {
375  }
376  else
377  {
378  m_LineColour.SetFromString("\000\000\000\000", 4); // Default is black
379  }
380 
381  if (m_OrigFillColour.IsSet())
382  {
384  }
385  else
386  {
387  m_FillColour.SetFromString("\000\000\000\377", 4); // Default is transparent
388  }
389 
390  MHVisible::Preparation(engine); // Prepare the base class.
391 }
392 
393 // MHEG Actions.
394 // Set the colours
395 void MHLineArt::SetFillColour(const MHColour &colour, MHEngine *engine)
396 {
397  m_FillColour.Copy(colour);
398  engine->Redraw(GetVisibleArea());
399 }
400 
401 void MHLineArt::SetLineColour(const MHColour &colour, MHEngine *engine)
402 {
403  m_LineColour.Copy(colour);
404  engine->Redraw(GetVisibleArea());
405 }
406 
407 void MHLineArt::SetLineWidth(int nWidth, MHEngine *engine)
408 {
409  m_nLineWidth = nWidth;
410  engine->Redraw(GetVisibleArea());
411 }
412 
413 void MHLineArt::SetLineStyle(int nStyle, MHEngine *engine)
414 {
415  m_LineStyle = nStyle;
416  engine->Redraw(GetVisibleArea());
417 }
418 
419 // The rectangle class doesn't add much to the LineArt class
420 void MHRectangle::PrintMe(FILE *fd, int nTabs) const
421 {
422  PrintTabs(fd, nTabs);
423  fprintf(fd, "{:Rectangle ");
424  MHLineArt::PrintMe(fd, nTabs + 1);
425  PrintTabs(fd, nTabs);
426  fprintf(fd, "}\n");
427 }
428 
429 // If this is opaque it obscures the underlying area.
431 {
432  if (! m_fRunning)
433  {
434  return QRegion();
435  }
436 
437  MHRgba lineColour = GetColour(m_LineColour);
438  MHRgba fillColour = GetColour(m_FillColour);
439 
440  // If the fill is transparent or semi-transparent we return an empty region and
441  // ignore the special case where the surrounding box is opaque.
442  if (fillColour.alpha() != 255)
443  {
444  return QRegion();
445  }
446 
447  if (lineColour.alpha() == 255 || m_nLineWidth == 0)
448  {
449  return QRegion(QRect(m_nPosX, m_nPosY, m_nBoxWidth, m_nBoxHeight));
450  }
451 
452  if (m_nBoxWidth <= 2 * m_nLineWidth || m_nBoxHeight <= 2 * m_nLineWidth)
453  {
454  return QRegion();
455  }
456  return QRegion(QRect(m_nPosX + m_nLineWidth, m_nPosY + m_nLineWidth,
458 }
459 
461 {
462  if (! m_fRunning)
463  {
464  return;
465  }
466 
467  if (m_nBoxWidth == 0 || m_nBoxHeight == 0)
468  {
469  return; // Can't draw zero sized boxes.
470  }
471 
472  // The bounding box is assumed always to be True.
473 
474  MHRgba lineColour = GetColour(m_LineColour);
475  MHRgba fillColour = GetColour(m_FillColour);
476  MHContext *d = engine->GetContext();
477 
478  // Fill the centre.
480  {
481  // If the area is very small but non-empty fill it with the line colour
482  d->DrawRect(m_nPosX, m_nPosY, m_nBoxWidth, m_nBoxHeight, lineColour);
483  }
484  else
485  {
486  d->DrawRect(m_nPosX + m_nLineWidth, m_nPosY + m_nLineWidth,
487  m_nBoxWidth - m_nLineWidth * 2, m_nBoxHeight - m_nLineWidth * 2, fillColour);
488  // Draw the lines round the outside. UK MHEG allows us to treat all line styles as solid.
489  // It isn't clear when we draw dashed and dotted lines what colour to put in the spaces.
490  d->DrawRect(m_nPosX, m_nPosY, m_nBoxWidth, m_nLineWidth, lineColour);
491  d->DrawRect(m_nPosX, m_nPosY + m_nBoxHeight - m_nLineWidth, m_nBoxWidth, m_nLineWidth, lineColour);
492  d->DrawRect(m_nPosX, m_nPosY + m_nLineWidth, m_nLineWidth, m_nBoxHeight - m_nLineWidth * 2, lineColour);
494  m_nLineWidth, m_nBoxHeight - m_nLineWidth * 2, lineColour);
495  }
496 }
497 
498 
500 {
501  // Engine Resp - optional
502  MHParseNode *pEngineResp = p->GetNamedArg(C_ENGINE_RESP);
503 
504  if (pEngineResp)
505  {
506  m_fEngineResp = pEngineResp->GetArgN(0)->GetBoolValue();
507  }
508 
509  // Highlight colour.
510  MHParseNode *phlCol = p->GetNamedArg(C_HIGHLIGHT_REF_COLOUR);
511 
512  if (phlCol)
513  {
514  m_highlightRefColour.Initialise(phlCol->GetArgN(0), engine);
515  }
516  else
517  {
519  }
520 
521  m_fHighlightStatus = false;
522  m_fInteractionStatus = false;
523 }
524 
525 void MHInteractible::PrintMe(FILE *fd, int nTabs) const
526 {
527  if (! m_fEngineResp)
528  {
529  PrintTabs(fd, nTabs);
530  fprintf(fd, ":EngineResp false\n");
531  }
532 
534  {
535  PrintTabs(fd, nTabs);
536  fprintf(fd, ":HighlightRefColour ");
537  m_highlightRefColour.PrintMe(fd, nTabs + 1);
538  fprintf(fd, "\n");
539  }
540 }
541 
543 {
544  m_fInteractionStatus = true;
545  engine->SetInteraction(this);
546  // The MHEG standard says: "generate visual feedback" here
547  // but it appears that any visual feedback is controlled only
548  // by the highlight status combined with engine-resp.
549 }
550 
552 {
553  if (newStatus) // Turning interaction on.
554  {
555  if (engine->GetInteraction() == nullptr) // No current interactible
556  {
557  Interaction(engine); // virtual function
558  }
559  }
560  else // Turning interaction off.
561  {
563  {
564  m_fInteractionStatus = false;
565  engine->SetInteraction(nullptr);
566  InteractionCompleted(engine); // Interaction is interrupted.
568  }
569  }
570 }
571 
573 {
574  if (newStatus == m_fHighlightStatus)
575  {
576  return;
577  }
578 
579  m_fHighlightStatus = newStatus;
580 
581  // If active redraw to show change of status.
583  {
584  engine->Redraw(m_parent->GetVisibleArea());
585  }
586 
587  // Generate the event for the change of highlight status.
589 }
590 
592 {
593  MHVisible::Initialise(p, engine);
594  MHInteractible::Initialise(p, engine);
595  //
596  MHParseNode *pOrientation = p->GetNamedArg(C_ORIENTATION);
597 
598  if (pOrientation)
599  {
600  m_orientation = (enum SliderOrientation)pOrientation->GetArgN(0)->GetEnumValue();
601  }
602 
603  // This is not optional.
604 
605  MHParseNode *pMin = p->GetNamedArg(C_MIN_VALUE);
606 
607  if (pMin)
608  {
609  m_orig_min_value = pMin->GetArgN(0)->GetIntValue();
610  }
611  else
612  {
613  m_orig_min_value = 1;
614  }
615 
616  MHParseNode *pMax = p->GetNamedArg(C_MAX_VALUE);
617 
618  if (pMax)
619  {
620  m_orig_max_value = pMax->GetArgN(0)->GetIntValue();
621  }
622  else
623  {
624  m_orig_max_value = m_orig_min_value - 1; // Unset
625  }
626 
627  MHParseNode *pInit = p->GetNamedArg(C_INITIAL_VALUE);
628 
629  if (pInit)
630  {
631  m_initial_value = pInit->GetArgN(0)->GetIntValue();
632  }
633  else
634  {
635  m_initial_value = m_orig_min_value; // Default is m_min_value
636  }
637 
638  MHParseNode *pPortion = p->GetNamedArg(C_INITIAL_PORTION);
639 
640  if (pPortion)
641  {
642  m_initial_portion = pPortion->GetArgN(0)->GetIntValue();
643  }
644  else
645  {
646  m_initial_portion = m_orig_min_value - 1; // Unset
647  }
648 
649  MHParseNode *pStep = p->GetNamedArg(C_STEP_SIZE);
650 
651  if (pStep)
652  {
653  m_orig_step_size = pStep->GetArgN(0)->GetIntValue();
654  }
655  else
656  {
657  m_orig_step_size = 1; // Unset
658  }
659 
660  MHParseNode *pStyle = p->GetNamedArg(C_SLIDER_STYLE);
661 
662  if (pStyle)
663  {
664  m_style = (enum SliderStyle)pStyle->GetArgN(0)->GetEnumValue();
665  }
666  else
667  {
668  m_style = SliderNormal;
669  }
670 
671  MHParseNode *pslCol = p->GetNamedArg(C_SLIDER_REF_COLOUR);
672 
673  if (pslCol)
674  {
675  m_sliderRefColour.Initialise(pslCol->GetArgN(0), engine);
676  }
677  else
678  {
680  }
681 }
682 
683 static const char *rchOrientation[] =
684 {
685  "left", // 1
686  "right",
687  "up",
688  "down" // 4
689 };
690 
691 // Look up the Orientation. Returns zero if it doesn't match. Used in the text parser only.
692 int MHSlider::GetOrientation(const char *str)
693 {
694  for (int i = 0; i < (int)(sizeof(rchOrientation) / sizeof(rchOrientation[0])); i++)
695  {
696  if (strcasecmp(str, rchOrientation[i]) == 0)
697  {
698  return (i + 1); // Numbered from 1
699  }
700  }
701 
702  return 0;
703 }
704 
705 static const char *rchStyle[] =
706 {
707  "normal", // 1
708  "thermometer",
709  "proportional" // 3
710 };
711 
712 int MHSlider::GetStyle(const char *str)
713 {
714  for (int i = 0; i < (int)(sizeof(rchStyle) / sizeof(rchStyle[0])); i++)
715  {
716  if (strcasecmp(str, rchStyle[i]) == 0)
717  {
718  return (i + 1); // Numbered from 1
719  }
720  }
721 
722  return 0;
723 }
724 
725 void MHSlider::PrintMe(FILE *fd, int nTabs) const
726 {
727  PrintTabs(fd, nTabs);
728  fprintf(fd, "{:Slider ");
729  MHVisible::PrintMe(fd, nTabs + 1);
730  MHInteractible::PrintMe(fd, nTabs + 1);
731 
732  PrintTabs(fd, nTabs);
733  fprintf(fd, ":Orientation %s\n", rchOrientation[m_orientation-1]);
734 
736  {
737  PrintTabs(fd, nTabs + 1);
738  fprintf(fd, ":InitialValue %d\n", m_initial_value);
739  }
740 
741  if (m_orig_min_value != 1)
742  {
743  PrintTabs(fd, nTabs + 1);
744  fprintf(fd, ":MinValue %d\n", m_orig_min_value);
745  }
746 
748  {
749  PrintTabs(fd, nTabs + 1);
750  fprintf(fd, ":MaxValue %d\n", m_orig_max_value);
751  }
752 
754  {
755  PrintTabs(fd, nTabs + 1);
756  fprintf(fd, ":InitialPortion %d\n", m_initial_portion);
757  }
758 
759  if (m_orig_step_size != 1)
760  {
761  PrintTabs(fd, nTabs + 1);
762  fprintf(fd, ":StepSize %d\n", m_orig_step_size);
763  }
764 
765  if (m_style != SliderNormal)
766  {
767  PrintTabs(fd, nTabs + 1);
768  fprintf(fd, ":SliderStyle %s\n", rchStyle[m_style-1]);
769  }
770 
771  if (m_sliderRefColour.IsSet())
772  {
773  PrintTabs(fd, nTabs + 1);
774  fprintf(fd, ":SliderRefColour ");
775  m_sliderRefColour.PrintMe(fd, nTabs + 2);
776  fprintf(fd, "\n");
777  }
778 
779  PrintTabs(fd, nTabs);
780  fprintf(fd, "}\n");
781 }
782 
783 // The MHEG standard doesn't define where the internal values are
784 // initialised. Assume it's during preparation.
786 {
787  MHVisible::Preparation(engine);
793 }
794 
796 {
797  MHContext *d = engine->GetContext();
798  MHRgba colour;
799 
801  {
803  }
804  else
805  {
806  colour = GetColour(m_sliderRefColour);
807  }
808 
809  int major = m_nBoxHeight; // Direction of change.
810  if (m_orientation == SliderLeft || m_orientation == SliderRight)
811  major = m_nBoxWidth;
812 
813  if (m_max_value <= m_min_value)
814  {
815  return; // Avoid divide by zero if error.
816  }
817 
818  if (m_style == SliderNormal)
819  {
820  // This is drawn as a 9 pixel wide "thumb" at the position.
821  major -= 9; // Width of "thumb"
822  int posn = major * (m_slider_value - m_min_value) / (m_max_value - m_min_value);
823 
824  switch (m_orientation)
825  {
826  case SliderLeft:
827  d->DrawRect(m_nPosX + posn, m_nPosY, 9, m_nBoxHeight, colour);
828  break;
829  case SliderRight:
830  d->DrawRect(m_nPosX + m_nBoxWidth - posn - 9, m_nPosY, 9, m_nBoxHeight, colour);
831  break;
832  case SliderUp:
833  d->DrawRect(m_nPosX, m_nPosY + m_nBoxHeight - posn - 9, m_nBoxWidth, 9, colour);
834  break;
835  case SliderDown:
836  d->DrawRect(m_nPosX, m_nPosY + posn, m_nBoxWidth, 9, colour);
837  break;
838  }
839  }
840  else
841  {
842  // Thermometer and proportional sliders are drawn as bars. Thermometers
843  // run from the start to the position, proportional sliders from the
844  // position for the "portion".
845  int start = 0;
846  int end = major * (m_slider_value - m_min_value) / (m_max_value - m_min_value);
847 
848  if (m_style == SliderProp)
849  {
850  start = end;
851  end = major * (m_slider_value + m_portion - m_min_value) / (m_max_value - m_min_value);
852  }
853 
854  switch (m_orientation)
855  {
856  case SliderLeft:
857  d->DrawRect(m_nPosX + start, m_nPosY, end - start, m_nBoxHeight, colour);
858  break;
859  case SliderRight:
860  d->DrawRect(m_nPosX + m_nBoxWidth - end, m_nPosY, end - start, m_nBoxHeight, colour);
861  break;
862  case SliderUp:
863  d->DrawRect(m_nPosX, m_nPosY + m_nBoxHeight - end, m_nBoxWidth, end - start, colour);
864  break;
865  case SliderDown:
866  d->DrawRect(m_nPosX, m_nPosY + start, m_nBoxWidth, end - start, colour);
867  break;
868  }
869 
870  }
871 }
872 
874 {
876  // All the interaction is handled by KeyEvent.
877 }
878 
879 // Called when the interaction has been terminated and we need
880 // to restore the state to non-interacting.
882 {
884  // Redraw with the interaction highlighting turned off
885  engine->Redraw(GetVisibleArea());
886 }
887 
888 // Called when a key is pressed. The only keys that have an effect are
889 // the Select and Cancel keys which both terminate the action and the
890 // arrow keys. The effect of the arrow keys depends on the orientation of
891 // the slider.
892 void MHSlider::KeyEvent(MHEngine *engine, int nCode)
893 {
894  switch (nCode)
895  {
896  case 15: // Select key
897  case 16: // Cancel key
898  m_fInteractionStatus = false;
899  engine->SetInteraction(nullptr);
900  InteractionCompleted(engine); // Interaction is interrupted.
902  break;
903 
904  case 1: // Up
905 
906  if (m_orientation == SliderUp)
907  {
908  Increment(engine);
909  }
910  else if (m_orientation == SliderDown)
911  {
912  Decrement(engine);
913  }
914 
915  break;
916 
917  case 2: // Down
918 
919  if (m_orientation == SliderUp)
920  {
921  Decrement(engine);
922  }
923  else if (m_orientation == SliderDown)
924  {
925  Increment(engine);
926  }
927 
928  break;
929 
930  case 3: // Left
931 
932  if (m_orientation == SliderLeft)
933  {
934  Increment(engine);
935  }
936  else if (m_orientation == SliderRight)
937  {
938  Decrement(engine);
939  }
940 
941  break;
942 
943  case 4: // Right
944 
945  if (m_orientation == SliderLeft)
946  {
947  Decrement(engine);
948  }
949  else if (m_orientation == SliderRight)
950  {
951  Increment(engine);
952  }
953 
954  break;
955 
956  }
957 }
958 
960 {
962  {
964  engine->Redraw(GetVisibleArea());
966  }
967 }
968 
970 {
972  {
974  engine->Redraw(GetVisibleArea());
976  }
977 }
978 
979 void MHSlider::Step(int nbSteps, MHEngine *engine)
980 {
981  m_step_size = nbSteps;
982 
983  if (m_fRunning)
984  {
985  engine->Redraw(GetVisibleArea());
986  }
987 
989 }
990 
991 void MHSlider::SetSliderValue(int newValue, MHEngine *engine)
992 {
993  m_slider_value = newValue;
994 
995  if (m_fRunning)
996  {
997  engine->Redraw(GetVisibleArea());
998  }
999 
1000  engine->EventTriggered(this, EventSliderValueChanged);
1001 }
1002 
1003 void MHSlider::SetPortion(int newPortion, MHEngine *engine)
1004 {
1005  m_portion = newPortion;
1006 
1007  if (m_fRunning)
1008  {
1009  engine->Redraw(GetVisibleArea());
1010  }
1011 
1012  engine->EventTriggered(this, EventSliderValueChanged);
1013 }
1014 
1015 // Additional action defined in UK MHEG.
1016 void MHSlider::SetSliderParameters(int newMin, int newMax, int newStep, MHEngine *engine)
1017 {
1018  m_min_value = newMin;
1019  m_max_value = newMax;
1020  m_step_size = newStep;
1021  m_slider_value = newMin;
1022 
1023  if (m_fRunning)
1024  {
1025  engine->Redraw(GetVisibleArea());
1026  }
1027 
1028  engine->EventTriggered(this, EventSliderValueChanged);
1029 }
1030 
1031 
1033 {
1034  MHVisible::Initialise(p, engine);
1035  MHInteractible::Initialise(p, engine);
1036  //
1037 }
1038 
1039 void MHEntryField::PrintMe(FILE *fd, int nTabs) const
1040 {
1041  PrintTabs(fd, nTabs);
1042  fprintf(fd, "{:EntryField ");
1043  MHVisible::PrintMe(fd, nTabs + 1);
1044  MHInteractible::PrintMe(fd, nTabs);
1045  fprintf(fd, "****TODO\n");
1046  PrintTabs(fd, nTabs);
1047  fprintf(fd, "}\n");
1048 }
1049 
1051 {
1052  MHVisible::Initialise(p, engine);
1053  //
1054 }
1055 
1056 void MHButton::PrintMe(FILE *fd, int nTabs) const
1057 {
1058  MHVisible::PrintMe(fd, nTabs);
1059  //
1060 }
1061 
1063 {
1064  MHButton::Initialise(p, engine);
1065  //
1066 }
1067 
1068 void MHHotSpot::PrintMe(FILE *fd, int nTabs) const
1069 {
1070  PrintTabs(fd, nTabs);
1071  fprintf(fd, "{:Hotspot ");
1072  MHButton::PrintMe(fd, nTabs + 1);
1073  fprintf(fd, "****TODO\n");
1074  PrintTabs(fd, nTabs);
1075  fprintf(fd, "}\n");
1076 }
1077 
1079 {
1080  MHButton::Initialise(p, engine);
1081  //
1082 }
1083 
1084 void MHPushButton::PrintMe(FILE *fd, int nTabs) const
1085 {
1086  PrintTabs(fd, nTabs);
1087  fprintf(fd, "{:PushButton ");
1088  MHButton::PrintMe(fd, nTabs + 1);
1089  fprintf(fd, "****TODO\n");
1090  PrintTabs(fd, nTabs);
1091  fprintf(fd, "}\n");
1092 }
1093 
1095 {
1096  MHPushButton::Initialise(p, engine);
1097  //
1098 }
1099 
1100 void MHSwitchButton::PrintMe(FILE *fd, int nTabs) const
1101 {
1102  PrintTabs(fd, nTabs);
1103  fprintf(fd, "{:SwitchButton ");
1104  MHPushButton::PrintMe(fd, nTabs + 1);
1105  fprintf(fd, "****TODO\n");
1106  PrintTabs(fd, nTabs);
1107  fprintf(fd, "}\n");
1108 }
1109 
1110 
1112 {
1113  MHElemAction::Initialise(p, engine);
1114 
1115  if (p->GetArgCount() > 1)
1116  {
1117  MHParseNode *pIndexed = p->GetNamedArg(C_NEW_COLOUR_INDEX);
1118  MHParseNode *pAbsolute = p->GetNamedArg(C_NEW_ABSOLUTE_COLOUR);
1119 
1120  if (pIndexed)
1121  {
1123  m_Indexed.Initialise(pIndexed->GetArgN(0), engine);
1124  }
1125  else if (pAbsolute)
1126  {
1128  m_Absolute.Initialise(pAbsolute->GetArgN(0), engine);
1129  }
1130  }
1131 }
1132 
1133 void MHSetColour::PrintArgs(FILE *fd, int /*nTabs*/) const
1134 {
1135  if (m_ColourType == CT_Indexed)
1136  {
1137  fprintf(fd, ":NewColourIndex ");
1138  m_Indexed.PrintMe(fd, 0);
1139  }
1140  else if (m_ColourType == CT_Absolute)
1141  {
1142  fprintf(fd, ":NewAbsoluteColour ");
1143  m_Absolute.PrintMe(fd, 0);
1144  }
1145 }
1146 
1148 {
1149  MHObjectRef target;
1150  m_Target.GetValue(target, engine); // Get the item to set.
1151  MHColour newColour;
1152 
1153  switch (m_ColourType)
1154  {
1155  case CT_None:
1156  {
1157  // If the colour is not specified use "transparent".
1158  newColour.SetFromString("\000\000\000\377", 4);
1159  break;
1160  }
1161  case CT_Absolute:
1162  {
1163  MHOctetString colour;
1164  m_Absolute.GetValue(colour, engine);
1165  newColour.m_ColStr.Copy(colour);
1166  break;
1167  }
1168  case CT_Indexed:
1169  newColour.m_nColIndex = m_Indexed.GetValue(engine);
1170  }
1171 
1172  SetColour(newColour, engine); // Set the colour of the appropriate portion of the visible
1173 }
void GetPosition(MHRoot *pXPosN, MHRoot *pYPosN) override
Definition: Visible.cpp:219
#define C_ORIGINAL_PALETTE_REF
Definition: ASN1Codes.h:111
static void Failure(const char *p)
Definition: ParseNode.cpp:43
void Preparation(MHEngine *engine) override
void Initialise(MHParseNode *p, MHEngine *engine)
enum MHSlider::SliderStyle SliderNormal
virtual void InteractionCompleted(MHEngine *)
Definition: Visible.h:152
MHVisible()=default
virtual void Interaction(MHEngine *engine)
Definition: Visible.cpp:542
#define C_INITIAL_PORTION
Definition: ASN1Codes.h:139
void PrintMe(FILE *fd, int nTabs) const override
bool m_fInteractionStatus
Definition: Visible.h:168
void AddToDisplayStack(MHVisible *pVis)
Definition: Engine.cpp:734
void KeyEvent(MHEngine *engine, int nCode) override
Definition: Visible.cpp:892
MHColour m_OrigFillColour
Definition: Visible.h:114
bool IsSet() const
Definition: BaseClasses.h:162
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Visible.cpp:1032
void BringToFront(MHEngine *engine) override
Definition: Visible.cpp:246
void PrintMe(FILE *fd, int nTabs) const
static int GetStyle(const char *str)
Definition: Visible.cpp:712
void SetLineStyle(int nStyle, MHEngine *engine) override
Definition: Visible.cpp:413
void Initialise(MHParseNode *p, MHEngine *engine)
Definition: Visible.cpp:499
int m_orig_max_value
Definition: Visible.h:226
int m_nOriginalPosX
Definition: Visible.h:75
void PrintMe(FILE *fd, int nTabs) const
QRegion GetOpaqueArea() override
Definition: Visible.cpp:430
void SetSliderValue(int newValue, MHEngine *engine) override
Definition: Visible.cpp:991
#define C_MAX_VALUE
Definition: ASN1Codes.h:136
static const char * rchOrientation[]
Definition: Visible.cpp:683
virtual void SetVariableValue(const MHUnion &)
Definition: Root.h:108
MHGenericObjectRef m_Target
Definition: BaseActions.h:46
void RemoveFromDisplayStack(MHVisible *pVis)
Definition: Engine.cpp:746
void Deactivation(MHEngine *engine) override
Definition: Visible.cpp:141
#define C_INITIAL_VALUE
Definition: ASN1Codes.h:138
#define C_ORIGINAL_LINE_STYLE
Definition: ASN1Codes.h:116
bool IsSet() const
Definition: BaseClasses.h:142
void Decrement(MHEngine *engine)
Definition: Visible.cpp:969
void InteractSetInteractionStatus(bool newStatus, MHEngine *engine)
Definition: Visible.cpp:551
void SetPortion(int newPortion, MHEngine *engine) override
Definition: Visible.cpp:1003
void PrintMe(FILE *fd, int nTabs) const override
Definition: Visible.cpp:84
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Visible.cpp:1078
virtual void Activation(MHEngine *engine)
Definition: Root.cpp:69
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Visible.cpp:1050
virtual bool GetRunningStatus()
Definition: Root.h:76
int m_nBoxWidth
Definition: Visible.h:79
void PutBefore(const MHRoot *pVis, const MHRoot *pRef)
Definition: Engine.cpp:790
MHObjectRef m_PaletteRef
Definition: Visible.h:83
virtual QRegion GetVisibleArea()
Definition: Visible.cpp:197
bool m_fAvailable
Definition: Root.h:251
void SetLineWidth(int nWidth, MHEngine *engine) override
Definition: Visible.cpp:407
int m_nPosY
Definition: Visible.h:82
void GetDefaultSliderRefColour(MHColour &colour)
Definition: Engine.cpp:1411
virtual void Deactivation(MHEngine *engine)
Definition: Root.cpp:85
static MHRgba GetColour(const MHColour &colour)
Definition: Visible.cpp:156
int GetValue(MHEngine *engine) const
int m_min_value
Definition: Visible.h:238
void Copy(const MHObjectRef &objr)
void GetValue(MHOctetString &str, MHEngine *engine) const
void PrintMe(FILE *fd, int nTabs) const override
Definition: Visible.cpp:1039
MHColour m_highlightRefColour
Definition: Visible.h:165
#define C_MIN_VALUE
Definition: ASN1Codes.h:137
unsigned char GetAt(int i) const
Definition: BaseClasses.h:122
int m_orig_min_value
Definition: Visible.h:227
virtual void SetColour(const MHColour &colour, MHEngine *engine)=0
void Copy(const MHColour &col)
static int GetOrientation(const char *str)
Definition: Visible.cpp:692
void SetPosition(int nXPosition, int nYPosition, MHEngine *engine) override
Definition: Visible.cpp:207
#define C_ORIGINAL_REF_FILL_COLOUR
Definition: ASN1Codes.h:118
MHLineArt()=default
void PrintMe(FILE *fd, int nTabs) const override
Definition: Visible.cpp:1084
void PrintMe(FILE *fd, int nTabs) const override
Definition: Visible.cpp:1100
bool m_fBorderedBBox
Definition: Visible.h:110
void Preparation(MHEngine *engine) override
Definition: Visible.cpp:785
MHContext * GetContext()
Definition: Engine.h:153
void PrintMe(FILE *fd, int nTabs) const override
Definition: Visible.cpp:1056
#define C_NEW_COLOUR_INDEX
Definition: ASN1Codes.h:263
void GetValue(MHObjectRef &ref, MHEngine *engine) const
void SetBoxSize(int nWidth, int nHeight, MHEngine *engine) override
Definition: Visible.cpp:225
void Perform(MHEngine *engine) override
Definition: Visible.cpp:1147
void Initialise(MHParseNode *p, MHEngine *engine)
void Redraw(const QRegion &region)
Definition: Engine.cpp:899
#define C_ORIENTATION
Definition: ASN1Codes.h:135
int m_LineStyle
Definition: Visible.h:117
int m_nOriginalLineWidth
Definition: Visible.h:111
MHColour m_LineColour
Definition: Visible.h:118
void SetFromString(const char *str, int nLen)
void PrintTabs(FILE *fd, int n)
Definition: ParseNode.cpp:34
SliderStyle
Definition: Visible.h:232
void SetFillColour(const MHColour &colour, MHEngine *engine) override
Definition: Visible.cpp:395
void GetDefaultHighlightRefColour(MHColour &colour)
Definition: Engine.cpp:1397
void Copy(const MHOctetString &str)
int m_orig_step_size
Definition: Visible.h:228
#define C_NEW_ABSOLUTE_COLOUR
Definition: ASN1Codes.h:264
int Size() const
Definition: BaseClasses.h:118
int m_nPosX
Definition: Visible.h:81
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Ingredients.cpp:49
int m_portion
Definition: Visible.h:241
int m_nOriginalBoxWidth
Definition: Visible.h:73
static const uint16_t * d
int GetIntValue()
Definition: ParseNode.cpp:170
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Visible.cpp:278
MHColour m_FillColour
Definition: Visible.h:118
void EventTriggered(MHRoot *pSource, enum EventType ev)
Definition: Engine.h:93
void Increment(MHEngine *engine)
Definition: Visible.cpp:959
#define C_ENGINE_RESP
Definition: ASN1Codes.h:134
void Preparation(MHEngine *engine) override
Definition: Visible.cpp:105
void SetInteraction(MHInteractible *p)
Definition: Engine.h:161
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Visible.cpp:50
MHColour m_sliderRefColour
Definition: Visible.h:234
enum MHSlider::SliderOrientation SliderLeft
MHVisible * m_parent
Definition: Visible.h:171
void Step(int nbSteps, MHEngine *engine) override
Definition: Visible.cpp:979
void PutBehind(const MHRoot *pVis, const MHRoot *pRef)
Definition: Engine.cpp:821
Definition: Root.h:43
void PrintMe(FILE *fd, int nTabs) const
enum MHSetColour::@13 m_ColourType
bool m_fRunning
Definition: Root.h:252
int m_nOriginalPosY
Definition: Visible.h:76
int m_OriginalLineStyle
Definition: Visible.h:113
int FILE
Definition: mythburn.py:110
void Destruction(MHEngine *engine) override
#define C_ORIGINAL_BOX_SIZE
Definition: ASN1Codes.h:109
void PrintMe(FILE *fd, int nTabs) const override
Definition: Visible.cpp:322
int m_initial_value
Definition: Visible.h:224
void SendToBack(MHEngine *engine) override
Definition: Visible.cpp:251
#define C_ORIGINAL_REF_LINE_COLOUR
Definition: ASN1Codes.h:117
int alpha() const
Definition: freemheg.h:85
void SetLineColour(const MHColour &colour, MHEngine *engine) override
Definition: Visible.cpp:401
int m_max_value
Definition: Visible.h:237
#define C_STEP_SIZE
Definition: ASN1Codes.h:140
int m_initial_portion
Definition: Visible.h:225
int m_nColIndex
Definition: BaseClasses.h:146
void SetPaletteRef(MHObjectRef newPalette, MHEngine *engine) override
Definition: Visible.cpp:240
void Initialise(MHParseNode *p, MHEngine *engine)
MHObjectRef m_OriginalPaletteRef
Definition: Visible.h:77
int GetEnumValue()
Definition: ParseNode.cpp:181
void Display(MHEngine *engine) override
Definition: Visible.cpp:795
void GetBoxSize(MHRoot *pWidthDest, MHRoot *pHeightDest) override
Definition: Visible.cpp:234
void Display(MHEngine *engine) override
Definition: Visible.cpp:460
#define MHLOG(__level, __text)
Definition: Logging.h:36
virtual void Initialise(MHParseNode *p, MHEngine *engine)
Definition: BaseActions.cpp:31
#define C_BORDERED_BOUNDING_BOX
Definition: ASN1Codes.h:114
void InteractionCompleted(MHEngine *engine) override
Definition: Visible.cpp:881
void PrintMe(FILE *fd, int nTabs) const override
Definition: Visible.cpp:725
bool GetBoolValue()
Definition: ParseNode.cpp:192
void BringToFront(const MHRoot *pVis)
Definition: Engine.cpp:760
void PrintMe(FILE *fd, int nTabs) const override
Definition: Visible.cpp:420
void Initialise(MHParseNode *p, MHEngine *engine)
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Visible.cpp:591
SliderOrientation
Definition: Visible.h:222
MHColour m_OrigLineColour
Definition: Visible.h:114
static const char * rchStyle[]
Definition: Visible.cpp:705
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Visible.cpp:1062
void Interaction(MHEngine *engine) override
Definition: Visible.cpp:873
MHParseNode * GetArgN(int n)
Definition: ParseNode.cpp:78
void PrintMe(FILE *fd, int nTabs) const override
Definition: Visible.cpp:1068
void SetSliderParameters(int newMin, int newMax, int newStep, MHEngine *engine) override
Definition: Visible.cpp:1016
int m_step_size
Definition: Visible.h:239
MHInteractible * GetInteraction(void)
Definition: Engine.h:160
void Preparation(MHEngine *engine) override
Definition: Visible.cpp:361
void Destruction(MHEngine *engine) override
Definition: Visible.cpp:122
bool m_fEngineResp
Definition: Visible.h:164
void Activation(MHEngine *engine) override
Definition: Visible.cpp:128
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Visible.cpp:1111
#define C_ORIGINAL_POSITION
Definition: ASN1Codes.h:110
#define C_SLIDER_REF_COLOUR
Definition: ASN1Codes.h:83
bool m_fHighlightStatus
Definition: Visible.h:167
#define C_SLIDER_STYLE
Definition: ASN1Codes.h:141
#define C_ORIGINAL_LINE_WIDTH
Definition: ASN1Codes.h:115
void InteractSetHighlightStatus(bool newStatus, MHEngine *engine)
Definition: Visible.cpp:572
int m_nLineWidth
Definition: Visible.h:116
int m_nBoxHeight
Definition: Visible.h:80
void SendToBack(const MHRoot *pVis)
Definition: Engine.cpp:775
#define C_HIGHLIGHT_REF_COLOUR
Definition: ASN1Codes.h:82
void PutBefore(const MHRoot *pRef, MHEngine *engine) override
Definition: Visible.cpp:256
void PrintMe(FILE *fd, int nTabs) const
void PrintArgs(FILE *fd, int nTabs) const override
Definition: Visible.cpp:1133
MHGenericOctetString m_Absolute
Definition: Visible.h:334
MHGenericInteger m_Indexed
Definition: Visible.h:333
void PrintMe(FILE *fd, int nTabs) const
Definition: Visible.cpp:525
MHOctetString m_ColStr
Definition: BaseClasses.h:145
void PutBehind(const MHRoot *pRef, MHEngine *engine) override
Definition: Visible.cpp:261
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Visible.cpp:1094
int m_slider_value
Definition: Visible.h:240
int m_nOriginalBoxHeight
Definition: Visible.h:74