Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

wintime.cpp

Go to the documentation of this file.
00001 // wintime.cpp
00002 //
00003 // Copyright (C) 2005, Chris Laurel <claurel@shatters.net>
00004 //
00005 // Win32 set time dialog box for Celestia
00006 //
00007 // This program is free software; you can redistribute it and/or
00008 // modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2
00010 // of the License, or (at your option) any later version.
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         // Convert from wide chars to a normal C string
00125         WideCharToMultiByte(CP_ACP, 0,
00126                             tzName, -1,
00127                             localTimeZoneName, sizeof(localTimeZoneName),
00128                             NULL, NULL);
00129         strcpy(localTimeZoneAbbrev, localTimeZoneName);
00130 
00131         // Not sure what GetTimeZoneInformation can return for the
00132         // time zone name.  On my XP system, it returns the string
00133         // "Pacific Standard Time", when we want PST . . .  So, we
00134         // call acronymify to do the conversion.  If the time zone
00135         // name doesn't contain any spaces, we assume that it's
00136         // already in acronym form.
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             // Set time to the current system time
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 }

Generated on Sat Jan 14 22:30:32 2006 for Celestia by  doxygen 1.4.1