BREW スケジューラー 〜 BREW C++ vCalendar プログラミング 〜
キーの処理
MainWindow
カレンダーを描画する MainWindow では、現在のカーソルの位置を SFXDate (日付) 型の変数である _cursor に記憶しています。 |
class MainWindow : public SFRPlainWindow { private: SFXDate _cursor; // カーソルの位置 // 以下省略 };
キーハンドラ
HANDLER_IMPLEMENT_BOOLEVENT(MainWindow, OnKey, event) { Bool result(false); switch (event.GetP16()) { case AVK_SELECT: // セレクトキーが押されたら ::new OneDayWindow(_cursor); result = true; break; case AVK_LEFT: _cursor.SubDay(1); // カーソルを左へ (1日引く) InvalidateContent(); // 再描画 result = true; break; case AVK_RIGHT: _cursor.AddDay(1); // カーソルを右へ (1日加える) InvalidateContent(); // 再描画 result = true; break; case AVK_UP: _cursor.SubDay(7); // カーソルを上へ (1週間引く) InvalidateContent(); // 再描画 result = true; break; case AVK_DOWN: _cursor.AddDay(7); // カーソルを下へ (1週間加える) InvalidateContent(); // 再描画 result = true; break; } return result; }
OneDayWindow
OneDayWindow は一日の全予定を表示します。 1 行目は新規データ作成用に「新規」の文字が、2 行目以降はその日のカレンダーデータの時刻と summary フィールド ( 内容 ) が表示されます。 |
SFMTYPEDEFCLASS(OneDayWindow) class OneDayWindow : public SFRPlainWindow { SFMSEALCOPY(OneDayWindow) private: SInt16 _displine; // 表示する行の先頭 SInt16 _cursor; // カーソル位置 SInt16 _maxline; // 表示する行数 SFXDateConst _date; // その日の日付 // _date の日付の先頭の VCalendar が何番目か SInt32 _index; // _date の日付の VCalendar の個数 SInt32 _number; public: OneDayWindow(SFXDateConstRef date) static_throws; virtual ~OneDayWindow(Void); HANDLER_DECLARE_VOIDRENDER(OnRenderContent) // 描画ハンドラ HANDLER_DECLARE_BOOLEVENT(OnKey) // キーハンドラ };
※ _cursor 変数 : 0 のときは「新規」、1 以上のときはその日のカレンダーデータ
キーハンドラ
HANDLER_IMPLEMENT_BOOLEVENT(OneDayWindow, OnKey, event) { Bool result(false); switch (event.GetP16()) { case AVK_CLR: // クリアー キーが押されたら、 // ウィンドウを閉じる result = Invoke(SFXEvent(SREVT_RESPONDER_TERMINATE, SRP16_TERMINATE_INVOKE, true)); break; case AVK_SELECT: if (_cursor <= 0) { //新規作成なら ::new CreateWindow(_date); // ウィンドウを生成 } else { // そうでないならカーソルが指しているデータを渡す // カーソルが指しているデータ VCalendarFilePtr vcal = SyncScheduler::GetVCalCollection()->Get( _index + _displine + _cursor - 1); ::new ModifyWindow(_date, vcal); // ウィンドウを生成 } result = true; break; case AVK_DOWN: // カーソルがデータの一番下にないなら if (_cursor + _displine < _number) { // カーソルが画面の一番下にあるなら if (_cursor >= _maxline - 1) { ++_displine; // 表示行を下へ } else { ++_cursor; // カーソルを下へ } } else { // カーソルが最下段なら // カーソルを最上段へ _displine = 0; _cursor = 0; } InvalidateContent(); // 再描画 result = true; break; case AVK_UP: if (_cursor == 0) { // カーソルが一番上にあるなら if (_displine > 0) { // 表示行を上へ動かせるなら --_displine; // 表示行を上へ動かす } else { // カーソルが最上段なら // カーソルを最下段へ _cursor = (_number < _maxline - 1) ? _number : _maxline - 1; _displine = (_number > _maxline - 1) ? (_number - _maxline + 1) : 0; } } else { --_cursor; // カーソルを上へ } InvalidateContent(); // 再描画 result = true; break; } return result; }
DataInputWindow
データの新規入力画面の CreateWindow とデータ修正画面の ModifyWindow は、処理内容がほとんど同じなので、どちらも DataInputWindow を継承しています。 |
SFMTYPEDEFCLASS(DataInputWindow) class DataInputWindow : public SFRPlainWindow { SFMSEALCOPY(DataInputWindow) protected: SFRBrewTextControlPtr _textHour; // 時間入力テキストコントロール SFRBrewTextControlPtr _textMinute; // 分入力テキストコントロール SFRBrewTextControlPtr _textContent; // 内容入力テキストコントロール SFRButtonControlPtr _buttonOk; // OK ボタン SFRButtonControlPtr _buttonCancel; // キャンセルボタン SFRLabelControlPtr _labelDate; // 日時ラベル SFRLabelControlPtr _labelHour; // 時間ラベル SFRLabelControlPtr _labelMinute; // 分ラベル SInt16 _fontHeight; // フォントの高さ SFXDateConst _date; // 今日の日付 public: DataInputWindow(SFXDateConstRef date) static_throws; virtual ~DataInputWindow(Void); virtual Void MakeData(SFXDateConstRef start, SFXAnsiStringConstRef summary) = 0; HANDLER_DECLARE_VOIDRENDER(OnRenderContent) // 描画ハンドラ HANDLER_DECLARE_BOOLEVENT(OnKey) // キーハンドラ HANDLER_DECLARE_VOIDCONTROL(OnOkButtonControl) // ボタンハンドラ HANDLER_DECLARE_VOIDCONTROL(OnCancelButtonControl) // ボタンハンドラ }; SFMTYPEDEFCLASS(CreateWindow) class CreateWindow : public DataInputWindow { SFMSEALCOPY(CreateWindow) public: CreateWindow(SFXDateConstRef date); virtual Void MakeData(SFXDateConstRef start, SFXAnsiStringConstRef summary); }; SFMTYPEDEFCLASS(ModifyWindow) class ModifyWindow : public DataInputWindow { SFMSEALCOPY(ModifyWindow) private: VCalendarFilePtr _vcal; // 修正するデータを保持 public: ModifyWindow(SFXDateConstRef date, VCalendarFilePtr vcal); virtual Void MakeData(SFXDateConstRef start, SFXAnsiStringConstRef summary); };
コンストラクタ ( 抜粋 )
DataInputWindow::DataInputWindow(SFXDateConstRef date) { // フォントの高さを取得 _fontHeight = SFXGraphics::GetFontHeight(AEE_FONT_NORMAL); SFXRectangleConst screenRect(GetContentWorld()); SFXRectangle rect(MENU_SIDE_MARGIN, MENU_TOP_MARGIN, screenRect.GetRight() - MENU_SIDE_MARGIN, _fontHeight); //長方形 // ラベルの生成 _labelDate = ::new SFRLabelControl(this, rect, date.Format("YYYY年MM月DD日")); rect.AddY(_fontHeight + MENU_SPACE); rect.SetSize(MENU_BOX_WIDTH, _fontHeight + TEXTBOX_REVISING); // 時間入力テキストコントロールの生成 _textHour = ::new SFRBrewTextControl(this, rect, ""); rect.AddX(MENU_BOX_WIDTH); // ラベルの生成 _labelHour = ::new SFRLabelControl(this, rect, "時"); rect.AddX(rect.GetWidth()); // 分入力テキストコントロールの生成 _textMinute = ::new SFRBrewTextControl(this, rect, ""); rect.AddX(MENU_BOX_WIDTH); // ラベルの生成 _labelMinute = ::new SFRLabelControl(this, rect, "分"); rect.SetX(MENU_SIDE_MARGIN); rect.AddY(_fontHeight + MENU_SPACE + TEXTBOX_REVISING); rect.SetSize(screenRect.GetRight() - 2 * MENU_SIDE_MARGIN, screenRect.GetBottom() - 4 * MENU_SPACE - 3 * _fontHeight - MENU_TOP_MARGIN); // 内容入力テキストコントロールの生成 _textContent = ::new SFRBrewTextControl(this, rect, ""); rect.Set(MENU_SIDE_MARGIN, screenRect.GetBottom() - MENU_SPACE - _fontHeight, MENU_BUTTON_WIDTH, _fontHeight); // 決定ボタンの生成 _buttonOk = ::new SFRButtonControl(this, rect, "決定"); rect.AddX(MENU_SPACE + MENU_BUTTON_WIDTH); // キャンセルボタンの生成 _buttonCancel = ::new SFRButtonControl(this, rect, "取消"); if (static_try()) { // キーハンドラの登録 static_throw(RegisterHandler(SFEVT_KEY, AVK_SELECT, HANDLER_AFTER, HANDLER_FUNCTION(SelectHandler))); if (static_try()) { if (_textHour != null && _textMinute != null && _textContent != null) { // 最大文字数設定 _textHour->SetMaxSize(2); _textMinute->SetMaxSize(2); _textContent->SetMaxSize(255); // フォーカスをあてる _textHour->SetStatusFocus(true); if (static_try()) { if (_buttonOk != null) { // ボタンハンドラの登録 static_throw(_buttonOk->RegisterHandler(SREVT_CONTROL, HANDLER_BEFORE,HANDLER_FUNCTION(OnOkButtonControl))); if (static_try()) { if (_buttonCancel != null) { // ボタンハンドラの登録 static_throw(_buttonCancel->RegisterHandler( SREVT_CONTROL, HANDLER_BEFORE, HANDLER_FUNCTION(OnCancelButtonControl))); } else { static_throw(SFERR_NO_MEMORY); } } } else { static_throw(SFERR_NO_MEMORY); } } } else { static_throw(SFERR_NO_MEMORY); } } } }
ModifyWindow に関する追加処理
ModifyWindow::ModifyWindow(SFXDateConstRef date, VCalendarFilePtr vcal) : DataInputWindow(date), // 親コンストラクタを呼び出す _vcal(vcal) // 修正するデータ { SFXDate start = _vcal->GetStartDate(); // テキストコントロールの初期値に時間を設定 _textHour->SetText(SFXWideString::Format("%d", start.GetHour())); // テキストコントロールの初期値に分を設定 _textMinute->SetText(SFXWideString::Format("%02d", start.GetMinute())); // テキストコントロールの初期値に内容を設定 _textContent->SetText(_vcal->GetSummary()); return; }
決定ボタンのハンドラ
HANDLER_IMPLEMENT_VOIDCONTROL(DataInputWindow, OnOkButtonControl, result, control) { SFXDate start(_date); // テキストコントロールから文字列を取得して数値に変換 SInt16 hour = static_cast<SInt16>(_textHour->GetText().AsSInt32()); if (hour < 0 || hour >= 24) { // 範囲チェック hour = 0; } start.SetHour(hour); // テキストコントロールから文字列を取得して数値に変換 SInt16 minute = static_cast<SInt16>(_textMinute->GetText().AsSInt32()); if (minute < 0 || minute >= 60) { // 範囲チェック minute = 0; } start.SetMinute(minute); start.SetSecond(0); //秒は0とする(仕様) // 内容入力テキストコントロールから文字列を取得 // ワイド文字列を Ansi 文字列に変換 SFXAnsiString summary(static_cast<SFXAnsiString>( _textContent->GetText())); // データ作成 (ウィンドウの種類によって異なる処理) MakeData(start, summary); // 後ろのウィンドウ (OneDayWindow) を取得 SFRResponderPtr oneDayWindow = GetNext(); // 自分自身と後ろのウィンドウの両方を閉じる Invoke(SFXEvent(SREVT_RESPONDER_TERMINATE, SRP16_TERMINATE_INVOKE, true)); oneDayWindow->Invoke(SFXEvent(SREVT_RESPONDER_TERMINATE, SRP16_TERMINATE_INVOKE, true)); return; }
CreateWindow の MakeData 関数
Void CreateWindow::MakeData(SFXDateConstRef start, SFXAnsiStringConstRef summary) { VCalendarFilePtr vcal = ::new VCalendarFile("1.0", start, start, summary); if (vcal != null) { SyncScheduler::GetVCalCollection()->Append(vcal); } return; }
ModifyWindow の MakeData 関数
Void ModifyWindow::MakeData(SFXDateConstRef start, SFXAnsiStringConstRef summary) { if (_vcal != null) { _vcal->Set(start, start, start ,summary); //修正する SyncScheduler::GetVCalCollection()->Update(_vcal); } return; }
VCalCollection の Update 関数
Void VCalCollection::Update(VCalendarFilePtr vcalendar) { _list.Remove(_list.IndexOf(vcalendar)); Append(vcalendar); vcalendar->SetFlag("m"); return; }