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