source: thomson/elec/CrO2/software/gui.cpp@ c2a9854

main
Last change on this file since c2a9854 was c2a9854, checked in by Adrien Destugues <pulkomandy@…>, 12 years ago

WIP explorer

  • Fill in the block list
  • HexEditor in progress.

Commiting because I'm trying to improve iupplusplus and want to make sure I can revert it if I fail.

git-svn-id: svn://localhost/thomson@16 85ae3b6b-dc8f-4344-a89d-598714f2e4e5

  • Property mode set to 100644
File size: 5.4 KB
RevLine 
[c7b4218]1/* CrO2 datassette emulator
2 * Copyright 2012, Adrien Destugues <pulkomandy@pulkomandy.ath.cx>
3 *
4 * Distributed under the terms of the MIT licence.
5 */
6
7#include "gui.h"
8
9#include "device.h"
10#include "k5.h"
11
12#include <stdint.h>
[c2a9854]13#include <string.h>
14#include <sstream>
15#include <iostream>
16
[c7b4218]17#include <iupcontrols.h>
18
19 // Start status poller "thread"
[192e299]20int pollStatus(Ihandle* ih)
21{
22 try {
[c7b4218]23 Ihandle* motoron = (Ihandle*)IupGetAttribute(ih, "target");
24
25 uint8_t status = Device::getDevice().getStatus();
26 if (status & 8)
27 IupSetAttribute(motoron, "VALUE", "0"); // motor OFF
28 else
29 IupSetAttribute(motoron, "VALUE", "1"); // motor ON
[192e299]30 } catch(const char*) {
31 // Silently ignore exception if device is not available - not a good
32 // idea to handle it from a timer...
33 // Keep the timer running so it starts working when the device is
34 // plugged
[c7b4218]35 }
[192e299]36 return IUP_DEFAULT;
37}
[c7b4218]38
39void startPolling(Ihandle* target) {
40 Ihandle* timer = IupTimer();
41
42 IupSetAttribute(timer, "target", (const char*)target);
43
44 IupSetAttribute(timer, "TIME", "300");
45 IupSetCallback(timer, "ACTION_CB", pollStatus);
46 IupSetAttribute(timer, "RUN", "YES");
47}
48
49/* UI */
50
51Gui::Gui(int* argc, char*** argv)
52{
53 file = NULL;
54
55 IupOpen(argc, argv);
[c2a9854]56 IupControlsOpen();
[c7b4218]57
58 Ihandle* menu_open = IupItem("Open", NULL);
[f9263dd]59 Ihandle* menu_exit = IupItem("Exit", NULL);
60 Callback<Gui>::create(menu_open, "ACTION", this, &Gui::menu_open);
61 Callback<Gui>::create(menu_exit, "ACTION", this, &Gui::menu_exit);
[c7b4218]62
63 Ihandle* menu = IupMenu(
64 IupSubmenu("File",
65 IupMenu(
66 menu_open,
[f9263dd]67 menu_exit,
[c7b4218]68 NULL
69 )
70 ),
71 NULL
72 );
73
74 // CONTROL
75 Ihandle* motoron = IupProgressBar();
76 IupSetAttribute(motoron, "RASTERSIZE", "16x16");
77
[c2a9854]78 Ihandle* playToggle = IupToggle("play", NULL);
79 Callback<Gui, int, int>::create(playToggle, "ACTION", this, &Gui::setPlaying);
80
[c7b4218]81 // EXPLORE
82 Ihandle* platformlist = IupList(NULL);
83 IupSetAttribute(platformlist, "EXPAND", "HORIZONTAL");
84 IupSetAttribute(platformlist, "DROPDOWN", "YES");
85 IupSetAttribute(platformlist, "1", "MO5");
86 IupSetAttribute(platformlist, "VALUE", "1");
87
[c2a9854]88 blocklist = IupTree();
[c7b4218]89 IupSetAttribute(blocklist, "EXPAND", "VERTICAL");
[c2a9854]90 IupSetAttribute(blocklist, "ADDEXPANDED", "NO");
91 IupSetAttribute(blocklist, "ADDROOT", "NO");
92 IupSetAttribute(blocklist, "IMAGELEAF", "IMGBLANK");
93 IupSetAttribute(blocklist, "RASTERSIZE", "140x200");
94 Callback<Gui, int, int, int>::create(blocklist, "SELECTION_CB", this, &Gui::selectBlock);
[c7b4218]95
[c2a9854]96 Ihandle* hexEd = IupMatrix(NULL);
[192e299]97
[c2a9854]98 // Setup title cells
99 IupSetAttribute(hexEd, "NUMLIN", "16");
100 IupSetAttribute(hexEd, "NUMCOL", "17");
101 IupSetAttribute(hexEd, "WIDTHDEF", "12");
102 IupSetAttribute(hexEd, "WIDTH17", "48");
103 IupSetAttribute(hexEd, "USETITLESIZE", "YES");
104 IupSetAttribute(hexEd, "FONT", "Courier, Bold 12");
105 IupSetAttribute(hexEd, "EXPAND", "YES");
106 Callback<Gui, const char*, int, int>::create(hexEd, "VALUE_CB", this, &Gui::matVal);
107
108 // WINDOW LAYOUT
[c7b4218]109 Ihandle* tabs = IupTabs(
110 IupVbox(
111 IupHbox(
112 IupLabel("Motor"),
113 motoron,
114 NULL
115 ),
116 IupHbox(
[192e299]117 playToggle,
[c7b4218]118 IupToggle("REC",NULL),
119 NULL
120 ),
121 NULL
122 ),
123 IupVbox(
124 IupHbox(
125 IupLabel("Format:"),
126 platformlist,
127 NULL
128 ),
129 IupHbox(
130 blocklist,
131 IupVbox(
[c2a9854]132 hexEd,
[c7b4218]133 IupLabel("Checksum:"),
134 NULL
135 ),
136 NULL
137 )
138 ),
139 NULL
140 );
141
142 IupSetAttribute(tabs,"TABTITLE0", "Control");
143 IupSetAttribute(tabs,"TABTITLE1", "Explore");
144
145 Ihandle* dialog = IupDialog(tabs);
146 IupSetAttribute(dialog, "TITLE", "CrO2 tape emulator");
147 IupSetAttributeHandle(dialog, "MENU", menu);
148 IupShow(dialog);
149
150 // Run the timer
151 startPolling(motoron);
152
[c2a9854]153 // TODO the IUP main loop is blocking - it may be wise to move it out of
154 // the constructor...
[c7b4218]155 IupMainLoop();
156}
157
158
159Gui::~Gui()
160{
161 delete file;
[c2a9854]162
163 IupControlsClose();
164 IupClose();
[c7b4218]165}
166
[192e299]167
[c7b4218]168int Gui::menu_open()
169{
170 char name[65536];
171 name[0] = 0;
172 if (IupGetFile(name) == 0)
173 {
174 // Load file
175 file = new K5(name);
[c2a9854]176
177 // Fill in EXPLORE tab
178 int count = file->getBlockCount();
179 int lastfile = -1;
180
181 for (int i = 0; i < count; ++i)
182 {
183 const K5::Block& blk = file->getBlock(i);
184 switch(blk.type)
185 {
186 case 0:
187 //start block
188 char name[12];
189 memcpy(name, blk.data, 11);
190 name[11] = 0;
191
192 IupSetAttributeId(blocklist, "INSERTBRANCH", lastfile, name);
193 lastfile = i;
194 break;
195 case 0xFF:
196 // end block
197 IupSetAttributeId(blocklist, "ADDLEAF", i-1, "EOF");
198 IupSetAttributeId(blocklist, "IMAGE", i, "IMGLEAF");
199 break;
200 default:
201 // regular block
202 IupSetAttributeId(blocklist, "ADDLEAF", i-1, "DATA");
203 break;
204 }
205 }
[c7b4218]206 }
207 return IUP_DEFAULT;
208}
[192e299]209
210int Gui::menu_exit()
211{
212 return IUP_CLOSE;
213}
214
[c2a9854]215int Gui::selectBlock(int id, int what)
216{
217 if (what)
218 {
219 IupSetAttribute(hexEd, "REDRAW", "ALL");
220 }
221
222 return IUP_DEFAULT;
223}
224
225const char* Gui::matVal(int x, int y)
226{
227 if (x == 0)
228 {
229 switch(y)
230 {
231 case 0:
232 return "0x";
233 case 17:
234 return "ASCII";
235 default:
236 {
237 std::ostringstream name;
238 name << std::hex;
239 name << (y-1);
240 return name.str().c_str();
241 }
242 }
243 }
244
245 if (y == 0)
246 {
247 return "C";
248 }
249
250 return "V";
251}
252
[192e299]253int Gui::setPlaying(int state)
254{
255 if (state == 0)
256 {
257 // pause
258 } else {
259 // play
260 Device::getDevice().write(*file);
261 }
262
263 return IUP_DEFAULT;
264}
Note: See TracBrowser for help on using the repository browser.