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