1//============================================================================
2//
3// SSSS tt lll lll
4// SS SS tt ll ll
5// SS tttttt eeee ll ll aaaa
6// SSSS tt ee ee ll ll aa
7// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
8// SS SS tt ee ll ll aa aa
9// SSSS ttt eeeee llll llll aaaaa
10//
11// Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony
12// and the Stella Team
13//
14// See the file "License.txt" for information on usage and redistribution of
15// this file, and for a DISCLAIMER OF ALL WARRANTIES.
16//============================================================================
17
18#include "OSystem.hxx"
19#include "EventHandler.hxx"
20#include "Dialog.hxx"
21#include "Widget.hxx"
22#include "Font.hxx"
23
24#include "HelpDialog.hxx"
25
26// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
27HelpDialog::HelpDialog(OSystem& osystem, DialogContainer& parent,
28 const GUI::Font& font)
29 : Dialog(osystem, parent, font, "Help"),
30 myPage(1),
31 myNumPages(5)
32{
33 const int lineHeight = font.getLineHeight(),
34 fontWidth = font.getMaxCharWidth(),
35 fontHeight = font.getFontHeight(),
36 buttonWidth = font.getStringWidth("Defaults") + 20,
37 buttonHeight = font.getLineHeight() + 4;
38 int xpos, ypos;
39 WidgetArray wid;
40
41 // Set real dimensions
42 _w = 46 * fontWidth + 10;
43 _h = 12 * lineHeight + 20 + _th;
44
45 // Add Previous, Next and Close buttons
46 xpos = 10; ypos = _h - buttonHeight - 10;
47 myPrevButton =
48 new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
49 "Previous", GuiObject::kPrevCmd);
50 myPrevButton->clearFlags(Widget::FLAG_ENABLED);
51 wid.push_back(myPrevButton);
52
53 xpos += buttonWidth + 8;
54 myNextButton =
55 new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
56 "Next", GuiObject::kNextCmd);
57 wid.push_back(myNextButton);
58
59 xpos = _w - buttonWidth - 10;
60 ButtonWidget* b =
61 new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
62 "Close", GuiObject::kCloseCmd);
63 wid.push_back(b);
64 addCancelWidget(b);
65
66 xpos = 5; ypos = 5 + _th;
67 myTitle = new StaticTextWidget(this, font, xpos, ypos, _w - 10, fontHeight,
68 "", TextAlign::Center);
69
70 int lwidth = 13 * fontWidth;
71 xpos += 5; ypos += lineHeight + 4;
72 for(uInt8 i = 0; i < LINES_PER_PAGE; ++i)
73 {
74 myKey[i] =
75 new StaticTextWidget(this, font, xpos, ypos, lwidth,
76 fontHeight, "", TextAlign::Left);
77 myDesc[i] =
78 new StaticTextWidget(this, font, xpos+lwidth, ypos, _w - xpos - lwidth - 5,
79 fontHeight, "", TextAlign::Left);
80 ypos += fontHeight;
81 }
82
83 addToFocusList(wid);
84}
85
86// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
87void HelpDialog::updateStrings(uInt8 page, uInt8 lines, string& title)
88{
89 int i = 0;
90 auto ADD_BIND = [&](const string& k, const string& d)
91 {
92 myKeyStr[i] = k; myDescStr[i] = d; i++;
93 };
94 auto ADD_EVENT = [&](const Event::Type e, const string & d)
95 {
96 string desc = instance().eventHandler().getMappingDesc(e, EventMode::kEmulationMode);
97 ADD_BIND(desc.length() ? desc : "None", d);
98 };
99 auto ADD_TEXT = [&](const string& d) { ADD_BIND("", d); };
100 auto ADD_LINE = [&]() { ADD_BIND("", ""); };
101
102 switch(page)
103 {
104 case 1:
105 title = "Common commands";
106 ADD_EVENT(Event::Quit, "Quit emulation");
107 ADD_EVENT(Event::ExitMode, "Exit current mode/menu");
108 ADD_EVENT(Event::OptionsMenuMode, "Enter Options menu");
109 ADD_EVENT(Event::CmdMenuMode, "Toggle Command menu");
110 ADD_EVENT(Event::VidmodeIncrease, "Increase window size");
111 ADD_EVENT(Event::VidmodeDecrease, "Decrease window size");
112 ADD_EVENT(Event::ToggleFullScreen, "Toggle fullscreen /");
113 ADD_BIND("", " windowed mode");
114 ADD_EVENT(Event::IncreaseOverScan, "Increase overscan in FS mode");
115 ADD_EVENT(Event::DecreaseOverscan, "Decrease overscan in FS mode");
116 break;
117
118 case 2:
119 title = "Special commands";
120 ADD_EVENT(Event::IncreaseFormat, "Switch between NTSC/PAL/SECAM");
121 ADD_EVENT(Event::TogglePalette, "Switch palette");
122 ADD_EVENT(Event::TogglePhosphor, "Toggle 'phosphor' effect");
123 ADD_LINE();
124 ADD_EVENT(Event::ToggleGrabMouse, "Grab mouse (keep in window)");
125 ADD_EVENT(Event::HandleMouseControl, "Toggle controller for mouse");
126 ADD_EVENT(Event::ToggleSAPortOrder, "Toggle Stelladaptor left/right");
127 ADD_LINE();
128 ADD_EVENT(Event::VolumeIncrease, "Increase volume by 2%");
129 ADD_EVENT(Event::VolumeDecrease, "Decrease volume by 2%");
130 break;
131
132 case 3:
133 title = "TV effects";
134 ADD_EVENT(Event::VidmodeStd, "Disable TV effects");
135 ADD_EVENT(Event::VidmodeRGB, "Enable 'RGB' mode");
136 ADD_EVENT(Event::VidmodeSVideo, "Enable 'S-Video' mode");
137 ADD_EVENT(Event::VidModeComposite, "Enable 'Composite' mode");
138 ADD_EVENT(Event::VidModeBad, "Enable 'Badly adjusted' mode");
139 ADD_EVENT(Event::VidModeCustom, "Enable 'Custom' mode");
140 ADD_EVENT(Event::NextAttribute, "Select 'Custom' attribute");
141 ADD_EVENT(Event::IncreaseAttribute, "Modify 'Custom' attribute");
142 ADD_EVENT(Event::IncreasePhosphor, "Adjust phosphor blend");
143 ADD_EVENT(Event::ScanlinesIncrease, "Adjust scanline intensity");
144 break;
145
146 case 4:
147 title = "Developer commands";
148 ADD_EVENT(Event::DebuggerMode, "Toggle debugger mode");
149 ADD_EVENT(Event::ToggleFrameStats, "Toggle frame stats");
150 ADD_EVENT(Event::ToggleJitter, "Toggle TV 'jitter'");
151 ADD_EVENT(Event::ToggleColorLoss, "Toggle PAL color loss");
152 ADD_EVENT(Event::ToggleCollisions, "Toggle collisions");
153 ADD_EVENT(Event::ToggleFixedColors, "Toggle 'Debug colors' mode");
154 ADD_LINE();
155 ADD_EVENT(Event::ToggleTimeMachine, "Toggle 'Time Machine' mode");
156 ADD_EVENT(Event::SaveAllStates, "Save all 'Time Machine' states");
157 ADD_EVENT(Event::LoadAllStates, "Load all 'Time Machine' states");
158 break;
159
160 case 5:
161 title = "All other commands";
162 ADD_LINE();
163 ADD_BIND("Remapped Even", "ts");
164 ADD_TEXT("Most other commands can be");
165 ADD_TEXT("remapped. Please consult the");
166 ADD_TEXT("'Options/Input" + ELLIPSIS + "' dialog for");
167 ADD_TEXT("more information.");
168 break;
169 }
170
171 while(i < lines)
172 ADD_LINE();
173}
174
175// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
176void HelpDialog::displayInfo()
177{
178 string titleStr;
179 updateStrings(myPage, LINES_PER_PAGE, titleStr);
180
181 myTitle->setLabel(titleStr);
182 for(uInt8 i = 0; i < LINES_PER_PAGE; ++i)
183 {
184 myKey[i]->setLabel(myKeyStr[i]);
185 myDesc[i]->setLabel(myDescStr[i]);
186 }
187}
188
189// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
190void HelpDialog::handleCommand(CommandSender* sender, int cmd,
191 int data, int id)
192{
193 switch(cmd)
194 {
195 case GuiObject::kNextCmd:
196 ++myPage;
197 if(myPage >= myNumPages)
198 myNextButton->clearFlags(Widget::FLAG_ENABLED);
199 if(myPage >= 2)
200 myPrevButton->setFlags(Widget::FLAG_ENABLED);
201
202 displayInfo();
203 break;
204
205 case GuiObject::kPrevCmd:
206 --myPage;
207 if(myPage <= myNumPages)
208 myNextButton->setFlags(Widget::FLAG_ENABLED);
209 if(myPage <= 1)
210 myPrevButton->clearFlags(Widget::FLAG_ENABLED);
211
212 displayInfo();
213 break;
214
215 default:
216 Dialog::handleCommand(sender, cmd, data, 0);
217 }
218}
219