00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "wintime.h"
00013 #include <windows.h>
00014 #include <winuser.h>
00015 #include <commctrl.h>
00016 #include <time.h>
00017 #include "res/resource.h"
00018 #include <celengine/astro.h>
00019
00020
00021 class SetTimeDialog
00022 {
00023 public:
00024 SetTimeDialog(CelestiaCore*);
00025 ~SetTimeDialog();
00026
00027 void init(HWND _hDlg);
00028 double getTime() const;
00029 void setTime(const double _jd);
00030
00031 void updateControls();
00032
00033 LRESULT command(WPARAM wParam, LPARAM lParam);
00034 LRESULT notify(int id, const NMHDR& nmhdr);
00035
00036 private:
00037 HWND hDlg;
00038 CelestiaCore* appCore;
00039 double jd;
00040 bool useLocalTime;
00041 char localTimeZoneAbbrev[64];
00042 char localTimeZoneName[64];
00043 int localTimeZoneBiasInSeconds;
00044
00045 void getLocalTimeZoneInfo();
00046 };
00047
00048
00049 SetTimeDialog::SetTimeDialog(CelestiaCore* _appCore) :
00050 hDlg(0),
00051 appCore(_appCore),
00052 jd(astro::J2000),
00053 useLocalTime(false),
00054 localTimeZoneBiasInSeconds(0)
00055 {
00056 localTimeZoneAbbrev[0] = '\0';
00057 localTimeZoneName[0] = '\0';
00058 }
00059
00060
00061 SetTimeDialog::~SetTimeDialog()
00062 {
00063 }
00064
00065
00066 static void acronymify(char* words, int length)
00067 {
00068 int n = 0;
00069 char lastChar = ' ';
00070
00071 for (int i = 0; i < length; i++)
00072 {
00073 if (lastChar == ' ')
00074 words[n++] = words[i];
00075 lastChar = words[i];
00076 }
00077 words[n] = '\0';
00078 }
00079
00080
00081 void
00082 SetTimeDialog::init(HWND _hDlg)
00083 {
00084 hDlg = _hDlg;
00085
00086 SetWindowLong(hDlg, DWL_USER, reinterpret_cast<LPARAM>(this));
00087 getLocalTimeZoneInfo();
00088
00089 jd = appCore->getSimulation()->getTime();
00090 useLocalTime = appCore->getTimeZoneBias() != 0;
00091
00092 SendDlgItemMessage(hDlg, IDC_COMBOBOX_TIMEZONE, CB_ADDSTRING, 0, (LPARAM) "Universal Time");
00093 SendDlgItemMessage(hDlg, IDC_COMBOBOX_TIMEZONE, CB_ADDSTRING, 0, (LPARAM) localTimeZoneName);
00094
00095 SendDlgItemMessage(hDlg, IDC_COMBOBOX_TIMEZONE, CB_SETCURSEL, useLocalTime ? 1 : 0, 0);
00096
00097 updateControls();
00098 }
00099
00100
00101 void
00102 SetTimeDialog::getLocalTimeZoneInfo()
00103 {
00104 TIME_ZONE_INFORMATION tzi;
00105 DWORD dst = GetTimeZoneInformation(&tzi);
00106 if (dst != TIME_ZONE_ID_INVALID)
00107 {
00108 WCHAR* tzName = NULL;
00109 LONG dstBias = 0;
00110
00111 if (dst == TIME_ZONE_ID_STANDARD)
00112 {
00113 dstBias = tzi.StandardBias;
00114 tzName = tzi.StandardName;
00115 }
00116 else if (dst == TIME_ZONE_ID_DAYLIGHT)
00117 {
00118 dstBias = tzi.DaylightBias;
00119 tzName = tzi.DaylightName;
00120 }
00121
00122 localTimeZoneBiasInSeconds = (tzi.Bias + dstBias) * -60;
00123
00124
00125 WideCharToMultiByte(CP_ACP, 0,
00126 tzName, -1,
00127 localTimeZoneName, sizeof(localTimeZoneName),
00128 NULL, NULL);
00129 strcpy(localTimeZoneAbbrev, localTimeZoneName);
00130
00131
00132
00133
00134
00135
00136
00137 if (strchr(localTimeZoneAbbrev, ' ') != NULL)
00138 acronymify(localTimeZoneAbbrev, strlen(localTimeZoneAbbrev));
00139 }
00140 }
00141
00142
00143 double
00144 SetTimeDialog::getTime() const
00145 {
00146 return jd;
00147 }
00148
00149
00150 void
00151 SetTimeDialog::setTime(double _jd)
00152 {
00153 jd = _jd;
00154 }
00155
00156
00157 void
00158 SetTimeDialog::updateControls()
00159 {
00160 HWND timeItem = NULL;
00161 HWND dateItem = NULL;
00162 SYSTEMTIME sysTime;
00163 double tzjd = jd;
00164
00165 if (useLocalTime)
00166 tzjd += localTimeZoneBiasInSeconds / 86400.0;
00167
00168 astro::Date newTime(tzjd);
00169
00170 sysTime.wYear = newTime.year;
00171 sysTime.wMonth = newTime.month;
00172 sysTime.wDay = newTime.day;
00173 sysTime.wDayOfWeek = ((int) ((double) newTime + 0.5) + 1) % 7;
00174 sysTime.wHour = newTime.hour;
00175 sysTime.wMinute = newTime.minute;
00176 sysTime.wSecond = (int) newTime.seconds;
00177 sysTime.wMilliseconds = 0;
00178
00179 dateItem = GetDlgItem(hDlg, IDC_DATEPICKER);
00180 if (dateItem != NULL)
00181 {
00182 DateTime_SetFormat(dateItem, "dd' 'MMM' 'yyy");
00183 DateTime_SetSystemtime(dateItem, GDT_VALID, &sysTime);
00184 }
00185 timeItem = GetDlgItem(hDlg, IDC_TIMEPICKER);
00186 if (timeItem != NULL)
00187 {
00188 char dateFormat[256];
00189 char* timeZoneName = useLocalTime ? localTimeZoneAbbrev : "UTC";
00190 sprintf(dateFormat, "HH':'mm':'ss' %s'", timeZoneName);
00191 DateTime_SetFormat(timeItem, dateFormat);
00192 DateTime_SetSystemtime(timeItem, GDT_VALID, &sysTime);
00193 }
00194 }
00195
00196
00197 LRESULT
00198 SetTimeDialog::command(WPARAM wParam, LPARAM lParam)
00199 {
00200 switch (LOWORD(wParam))
00201 {
00202 case IDOK:
00203 appCore->tick();
00204 appCore->getSimulation()->setTime(jd);
00205 appCore->setTimeZoneBias(useLocalTime ? 1 : 0);
00206 EndDialog(hDlg, 0);
00207 return TRUE;
00208
00209 case IDCANCEL:
00210 EndDialog(hDlg, 0);
00211 return TRUE;
00212
00213 case IDC_SETCURRENTTIME:
00214
00215 setTime((double) time(NULL) / 86400.0 + (double) astro::Date(1970, 1, 1));
00216 updateControls();
00217 return TRUE;
00218
00219 case IDC_COMBOBOX_TIMEZONE:
00220 if (HIWORD(wParam) == CBN_SELCHANGE)
00221 {
00222 LRESULT selection = SendMessage((HWND) lParam, CB_GETCURSEL, 0, 0);
00223 useLocalTime = (selection == 1);
00224 updateControls();
00225 }
00226 return TRUE;
00227
00228 default:
00229 return FALSE;
00230 }
00231 }
00232
00233
00234 LRESULT
00235 SetTimeDialog::notify(int id, const NMHDR& hdr)
00236 {
00237 astro::Date newTime(jd);
00238
00239 if (hdr.code == DTN_DATETIMECHANGE)
00240 {
00241 LPNMDATETIMECHANGE change = (LPNMDATETIMECHANGE) &hdr;
00242 if (change->dwFlags == GDT_VALID)
00243 {
00244 if (id == IDC_DATEPICKER || id == IDC_TIMEPICKER)
00245 {
00246 SYSTEMTIME sysTime;
00247 SYSTEMTIME sysDate;
00248 DateTime_GetSystemtime(GetDlgItem(hDlg, IDC_TIMEPICKER), &sysTime);
00249 DateTime_GetSystemtime(GetDlgItem(hDlg, IDC_DATEPICKER), &sysDate);
00250 newTime.year = (int16) sysDate.wYear;
00251 newTime.month = sysDate.wMonth;
00252 newTime.day = sysDate.wDay;
00253 newTime.hour = sysTime.wHour;
00254 newTime.minute = sysTime.wMinute;
00255 newTime.seconds = sysTime.wSecond + (double) sysTime.wMilliseconds / 1000.0;
00256
00257 jd = (double) newTime;
00258 if (useLocalTime)
00259 jd -= localTimeZoneBiasInSeconds / 86400.0;
00260 }
00261 }
00262 }
00263
00264 return TRUE;
00265 }
00266
00267
00268 static BOOL APIENTRY
00269 SetTimeProc(HWND hDlg,
00270 UINT message,
00271 UINT wParam,
00272 LONG lParam)
00273 {
00274 SetTimeDialog* timeDialog = reinterpret_cast<SetTimeDialog*>(GetWindowLong(hDlg, DWL_USER));
00275
00276 switch (message)
00277 {
00278 case WM_INITDIALOG:
00279 {
00280 timeDialog = reinterpret_cast<SetTimeDialog*>(lParam);
00281 if (timeDialog == NULL)
00282 return EndDialog(hDlg, 0);
00283
00284 timeDialog->init(hDlg);
00285 }
00286 return TRUE;
00287
00288 case WM_COMMAND:
00289 return timeDialog->command(wParam, lParam);
00290
00291 case WM_NOTIFY:
00292 return timeDialog->notify((int) wParam, *reinterpret_cast<NMHDR*>(lParam));
00293 }
00294
00295 return FALSE;
00296 }
00297
00298
00299 void
00300 ShowSetTimeDialog(HINSTANCE appInstance,
00301 HWND appWindow,
00302 CelestiaCore* appCore)
00303 {
00304 SetTimeDialog* timeDialog = new SetTimeDialog(appCore);
00305
00306 DialogBoxParam(appInstance, MAKEINTRESOURCE(IDD_SETTIME), appWindow, SetTimeProc, reinterpret_cast<LPARAM>(timeDialog));
00307
00308 delete timeDialog;
00309 }