Update copyright date; remove old CVS keyword
[ctsim.git] / src / backgroundmgr.cpp
1 /*****************************************************************************
2 ** FILE IDENTIFICATION
3 **
4 **   Name:          backgroundmgr.cpp
5 **   Purpose:       Background manager class
6 **   Programmer:    Kevin Rosenberg
7 **   Date Started:  February 2001
8 **
9 **  This is part of the CTSim program
10 **  Copyright (C) 1983-2009 Kevin Rosenberg
11 **
12 **  This program is free software; you can redistribute it and/or modify
13 **  it under the terms of the GNU General Public License (version 2) as
14 **  published by the Free Software Foundation.
15 **
16 **  This program is distributed in the hope that it will be useful,
17 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
18 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 **  GNU General Public License for more details.
20 **
21 **  You should have received a copy of the GNU General Public License
22 **  along with this program; if not, write to the Free Software
23 **  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24 ******************************************************************************/
25
26 #include "wx/wxprec.h"
27
28 #ifndef WX_PRECOMP
29 #include "wx/wx.h"
30 #endif
31
32 #include "ct.h"
33 #include "ctsim.h"
34 #include "docs.h"
35 #include "views.h"
36 #include "backgroundsupr.h"
37 #include "backgroundmgr.h"
38
39 #ifdef HAVE_WXTHREADS
40
41 int BackgroundManager::s_iNextButtonID = 0;
42
43 IMPLEMENT_DYNAMIC_CLASS(BackgroundManager, wxMiniFrame)
44 BEGIN_EVENT_TABLE(BackgroundManager, wxMiniFrame)
45 EVT_MENU(BackgroundSupervisor::MSG_BACKGROUND_SUPERVISOR_ADD, BackgroundManager::OnAddTask)
46 EVT_MENU(BackgroundSupervisor::MSG_BACKGROUND_SUPERVISOR_REMOVE, BackgroundManager::OnRemoveTask)
47 EVT_MENU(BackgroundSupervisor::MSG_BACKGROUND_SUPERVISOR_UNIT_TICK, BackgroundManager::OnUnitTick)
48 EVT_CLOSE(BackgroundManager::OnCloseWindow)
49 EVT_COMMAND_RANGE(0, 30000, wxEVT_COMMAND_BUTTON_CLICKED, BackgroundManager::OnCancelButton)
50 END_EVENT_TABLE()
51
52
53 BackgroundManager::BackgroundManager ()
54   : wxMiniFrame (theApp->getMainFrame(), -1, _T("Background Tasks"), wxPoint(0,0), wxSize(210, 50))
55 {
56   m_iNumTasks = 0;
57   m_pCanvas = new BackgroundManagerCanvas (this);
58   theApp->setIconForFrame (this);
59
60   m_sizeGauge.Set (70, 20);
61   m_sizeLabel.Set (140, 20);
62   m_sizeBorder.Set (4, 4);
63   m_sizeCellSpacing.Set (3, 3);
64   m_sizeButton.Set (70, 20);
65
66   m_sizeCell.Set (m_sizeGauge.x + m_sizeLabel.x + m_sizeCellSpacing.x + m_sizeButton.x, 25);
67
68   theApp->getMainFrame()->SetFocus();
69   Show(false);
70 }
71
72
73 BackgroundManager::~BackgroundManager()
74 {
75 }
76
77 void
78 BackgroundManager::OnCloseWindow (wxCloseEvent& event)
79 {
80   if (theApp->getMainFrame()->getShuttingDown())
81     wxMiniFrame::OnCloseWindow (event);
82   else
83     event.Veto();
84 }
85
86 void
87 BackgroundManager::OnUnitTick (wxCommandEvent& event)
88 {
89   int iUnits = event.GetInt();
90
91   BackgroundSupervisor* pSupervisor = reinterpret_cast<BackgroundSupervisor*>(event.GetClientData());
92   if (pSupervisor == NULL) {
93     sys_error (ERR_SEVERE, "Received NULL task [BackgroundManager::OnUnitTick]");
94     return;
95   }
96
97   BackgroundManagerTask* pTask = lookupTask (pSupervisor);
98   if (pTask == NULL) {
99           sys_error (ERR_SEVERE, "Error looking up task [BackgroundManager::OnUnitTick]");
100           return;
101   }
102   pTask->gauge()->SetValue (iUnits);
103 }
104
105 void
106 BackgroundManager::OnAddTask (wxCommandEvent& event)
107 {
108   int iNumUnits = event.GetInt();
109   const char* const pszTaskName = event.GetString().mb_str(wxConvUTF8);
110   BackgroundSupervisor* pSupervisor = reinterpret_cast<BackgroundSupervisor*>(event.GetClientData());
111   if (pSupervisor == NULL) {
112     sys_error (ERR_SEVERE, "Received NULL supervisor [BackgroundManager::OnAddTask]");
113     return;
114   }
115
116   wxCriticalSectionLocker locker (m_criticalSection);
117
118   int iNumTasks = m_vecpTasks.size();
119   std::vector<bool> vecPositionUsed (iNumTasks);  //vector of used table positions
120   for (int iP = 0; iP < iNumTasks; iP++)
121     vecPositionUsed[iP] = false;
122
123   for (TaskContainer::iterator iT = m_vecpTasks.begin(); iT != m_vecpTasks.end(); iT++) {
124     int iPosUsed = (*iT)->position();
125     if (iPosUsed < iNumTasks)
126       vecPositionUsed[iPosUsed] = true;
127   }
128
129   int iFirstUnusedPos = iNumTasks;  // default is just past current number of tasks
130   for (int i = 0; i < iNumTasks; i++)
131     if (! vecPositionUsed[i]) {
132       iFirstUnusedPos = i;
133       break;
134     }
135
136   wxPoint posGauge (m_sizeBorder.x, m_sizeBorder.y + iFirstUnusedPos * m_sizeCell.y);
137   wxPoint posLabel (m_sizeBorder.x + m_sizeGauge.x, m_sizeBorder.y + iFirstUnusedPos * m_sizeCell.y);
138   wxPoint posButton (m_sizeBorder.x + m_sizeGauge.x + m_sizeLabel.x, m_sizeBorder.y + iFirstUnusedPos * m_sizeCell.y);
139   wxGauge* pGauge = new wxGauge (m_pCanvas, -1, iNumUnits, posGauge, m_sizeGauge);
140   wxStaticText* pLabel = new wxStaticText (m_pCanvas, -1, wxConvUTF8.cMB2WX(pszTaskName), posLabel, m_sizeLabel);
141   wxButton* pButton = new wxButton (m_pCanvas, s_iNextButtonID, _T("Cancel"), posButton, m_sizeButton, wxBU_LEFT);
142
143   BackgroundManagerTask* pTask = new BackgroundManagerTask (pSupervisor, pszTaskName,
144     iFirstUnusedPos, pGauge, pLabel, pButton, s_iNextButtonID);
145
146   m_vecpTasks.push_back (pTask);
147   m_iNumTasks++;
148   s_iNextButtonID++;
149
150   resizeWindow();
151   if (m_iNumTasks == 1) {
152     m_pCanvas->SetFocus();
153     Show(true);
154   }
155 }
156
157 void
158 BackgroundManager::OnRemoveTask (wxCommandEvent& event)
159 {
160   BackgroundSupervisor* pSupervisor = reinterpret_cast<BackgroundSupervisor*>(event.GetClientData());
161   if (pSupervisor == NULL) {
162     sys_error (ERR_SEVERE, "Received NULL task [BackgroundManager::OnRemoveTask]");
163     return;
164   }
165
166   wxCriticalSectionLocker locker (m_criticalSection);
167
168   bool bFound = false;
169   for (TaskContainer::iterator iTask = m_vecpTasks.begin(); iTask != m_vecpTasks.end(); iTask++) {
170     if ((*iTask)->supervisor() == pSupervisor) {
171           delete (*iTask)->gauge();
172             delete (*iTask)->label();
173             delete (*iTask)->button();
174       delete *iTask;
175       m_vecpTasks.erase (iTask);
176       m_iNumTasks--;
177             bFound = true;
178       break;
179     }
180   }
181   if (! bFound)  {
182           sys_error (ERR_SEVERE, "Unable to find supervisor [BackgroundManager::OnRemoveTask]");
183     return;
184   }
185   pSupervisor->ackRemoveBackgroundManager();
186   resizeWindow();
187   if (m_iNumTasks <= 0) {
188     m_pCanvas->SetFocus();
189     Show(false);
190   }
191 }
192
193 void
194 BackgroundManager::OnCancelButton (wxCommandEvent& event)
195 {
196   BackgroundManagerTask* pTask = lookupTask (event.GetId());
197   if (! pTask) {
198     sys_error (ERR_SEVERE, "Unable to lookup task for button");
199     return;
200   }
201
202   pTask->supervisor()->onCancel();
203 }
204
205 BackgroundManagerTask*
206 BackgroundManager::lookupTask (BackgroundSupervisor* pSupervisor)
207 {
208   BackgroundManagerTask* pTask = NULL;
209
210   wxCriticalSectionLocker locker (m_criticalSection);
211   for (TaskContainer::iterator iTask = m_vecpTasks.begin(); iTask != m_vecpTasks.end(); iTask++) {
212     if ((*iTask)->supervisor() == pSupervisor) {
213       pTask = *iTask;
214       break;
215     }
216   }
217
218   return pTask;
219 }
220
221 BackgroundManagerTask*
222 BackgroundManager::lookupTask (int iButtonID)
223 {
224   BackgroundManagerTask* pTask = NULL;
225
226   wxCriticalSectionLocker locker (m_criticalSection);
227   for (TaskContainer::iterator iTask = m_vecpTasks.begin(); iTask != m_vecpTasks.end(); iTask++) {
228     if ((*iTask)->buttonID() == iButtonID) {
229       pTask = *iTask;
230       break;
231     }
232   }
233
234   return pTask;
235 }
236
237 void
238 BackgroundManager::resizeWindow()
239 {
240   int iHighestPosition = -1;
241
242   wxCriticalSectionLocker lock (m_criticalSection);
243   for (TaskContainer::iterator i = m_vecpTasks.begin(); i != m_vecpTasks.end(); i++)
244     if (iHighestPosition < (*i)->position())
245       iHighestPosition = (*i)->position();
246
247   wxSize sizeWindow (m_sizeCell.x, m_sizeCell.y * (iHighestPosition + 1));
248   SetClientSize (sizeWindow);
249   m_pCanvas->Refresh();
250 }
251
252
253
254 IMPLEMENT_DYNAMIC_CLASS(BackgroundManagerCanvas, wxPanel)
255 BEGIN_EVENT_TABLE(BackgroundManagerCanvas, wxPanel)
256 END_EVENT_TABLE()
257
258 BackgroundManagerCanvas::BackgroundManagerCanvas (BackgroundManager* pMgr)
259 : wxPanel (pMgr), m_pBackgroundManager(pMgr)
260 {
261 }
262
263
264 #endif // HAVE_WXTHREADS