Компонент ввода диапазона дат (постановка)

Материал из GedeminWiki
(Различия между версиями)
Перейти к: навигация, поиск
(Детали реализации)
(Примечания)
 
(не показаны 64 промежуточные версии 2 участников)
Строка 1: Строка 1:
=== Требования ===
+
В большинстве случаев при построении отчета или фильтрации массива документов пользователь указывает период дат. Сейчас в Гедымине применяются два компонента ввода даты для указания начального и конечного дня периода. Предлагается реализовать простой и удобный визуальный компонент для ввода периода дат как набором с клавиатуры, так и путем выбора мышью. Минимальный период -- один день. Ввод даты окончания периода меньшей даты начала не допускается.
  
# Ввод единичной даты;
+
http://gsbelarus.com/gs/images/gs/2008/periodedit_1.png
# Ввод произвольного диапазона дат;
+
# Быстрый выбор диапазона:
+
## Год;
+
## Полугодие;
+
## Квартал;
+
## Месяц;
+
## Неделя;
+
# Быстрый ввод с клавиатуры с подстановкой текущей даты (текущего дня, месяца, года), подобно тому, как сейчас подставляются текущий день месяц и год по нажатию на клавишу пробел в [[TxDateEdit]];
+
# Использование метасимволов:
+
## c -- сегодня
+
## з -- завтра
+
## в -- вчера
+
## н -- текущая неделя
+
## пн -- прошлая неделя
+
## сн -- следующая неделя
+
## м -- текущий месяц
+
## пм -- прошлый месяц
+
## см -- следующий месяц
+
## к -- текущий квартал
+
## пк -- прошлый квартал
+
## ск -- следующий квартал
+
## г -- текущий год
+
## пг -- прошлый год
+
## сг -- следующий год
+
# Хранение последнего введенного значения. Причем, если был использован метосимвол, то сохранятся должен именно он, а не рассчитанные на основе его значения;
+
# Хранение истории введенных значений;
+
# Хранение последнего выбора пользователя (последней активной страницы в выпадающем окошке): ввод даты, диапазона, квартала, месяца и т.п.
+
# Возможность работы только с клавиатуры без помощи мыши;
+
# Компонент должен быть реализован ввиде автономного pas файла (группы pas файлов) и не иметь связей с кодом платформы [[Гедымин]].
+
  
=== Визуальный интерфейс ===
+
Компонент должен представлять собой поле ввода [[TEdit]] справа от которого расположена кнопка для вызова выпадающего окна.
  
Компонента должна представлять [[TCombobox]] или [[TPanel]] с расположенным на ней TCombobox, где в окошке редактирования производится ввод диапазона дат. Начальная дата и конечная дата разделяются символом '-'.
+
== Ввод периода с помощью мыши ==
  
Для ввода единичной даты, достаточно, чтобы одна из дат диапазона была пустой. После клика мышкой по элементу в правой части окошка редактирования (или при помощи клавиши стрелка вниз), под окошком ввода дат должен появляться элемент [[TPageControl]] со следующими закладками:
+
Диапазон дат можно указать мышью в выпадающем окне следующими способами:
  
# История - можно просмотреть и выбрать ранее введённые пользователем данные из списка [[TListBox]].
+
http://gsbelarus.com/gs/images/gs/2008/periodedit_2.png
# Произвольный выбор дат - можно выбрать даты диапазона из двух элементов-календарей [[TMonthCalendar]].
+
# Год - выбор года из списка TListBox.
+
# Квартал - выбора квартала по году из первой даты, если она есть. Выбирается из списка TListBox.
+
# Месяц - выбор месяца по году из первой даты, если она есть. выбирается из списка TListBox.
+
# Неделя - выбор недели по году из первой даты, если она есть. Выбирается из списка TListBox.
+
# День - выбор дня по году из первой даты, если она есть. Выбирается из списка TListBox.
+
  
=== Ввод с клавиатуры ===
+
Выпадающее окно разделено по вертикали на две части. В левой находится список выбора режима указания периода. В зависимости от режима справа располагается:
  
Исходное состояние: курсор попадает в поле ввода. Оно либо пустое, либо находящийся в нем текст выделяется, так что вводимые символы заменят его. Пользователь начинает вводить цифры. Первые две введенные цифры трактуются как номер дня. После них автоматически подставляется разделитель. Пользователь может так же ввести одну только цифру и ввести разделитель самостоятельно. Аналогичным образом, следующие две цифры трактуются как номер месяца.
+
* '''Год.''' Календарь для выбора года.
 +
* '''Квартал.''' Календарь для выбора года и квартала.
 +
* '''Месяц.''' Календарь для выбора года и месяца.
 +
* '''Неделя.''' Календарь для выбора года, месяца и недели.
 +
* '''День.''' Календарь для выбора года. месяца, дня.
 +
* '''Произвольный.''' Два календаря для выбора первого и последнего дня периода.
 +
* '''Шорт-кат.''' Список доступных шорт-катов.
 +
* '''История.''' Несколько последних периодов, выбранных пользователем.
  
=== Детали реализации ===
+
В правой части, внизу показывается текущий период. При клике мышкой он выбирается и окно закрывается. В зависимости от режима выбора надпись имеет следующий вид:
  
Визуальный компонент должен быть наследован от стандартного компонента [[TPanel]].
+
* Год -- "Текущий год: 2010 г."
 +
* Квартал -- "Текущий квартал: 4 кв. 2010 г."
 +
* Месяц -- "Текущий месяц: август 2010 г."
 +
* Неделя -- "Текущая неделя: 22 нд. 2010 г."
 +
* День -- "Сегодня: 22.08.2010"
  
[[Category:Постановка]]
+
В режиме выбора произвольного периода под каждым календарем выводится налпись "Сегодня: 22.08.2010". Клик по ней устанавливает на календаре текущую дату, но не закрывает компонент выбора.
 +
 
 +
После выбора периода окно закрывается. Выпадающее окно можно закрыть без выбора периода клавишей Esc, либо кликнув мышью за его пределами.
 +
 
 +
Для отображения календаря воспользуемся идеями из Windows 7.
 +
 
 +
== Ввод периода с помощью клавиатуры ==
 +
 
 +
В поле ввода пользователю предоставляется несколько вариантов ввода временного отрезка:
 +
 
 +
http://gsbelarus.com/gs/images/gs/2008/periodedit_3.png
 +
 
 +
Самый очевидный вариант -- ввод двух дат. Например, 01.01.2009-31.12.2009.
 +
 
 +
Полный формат даты -- когда указан день, месяц и год. Сокращенный -- если хотя бы одна из частей даты пропущена.
 +
 
 +
http://gsbelarus.com/gs/images/gs/2008/periodedit_4.png
 +
 
 +
{| border="1" cellpadding="2" cellspacing="0" style="border-collapse:collapse;"
 +
!style="background:#ffdead;"| Сокращенная дата
 +
!style="background:#ffdead;"| Единственная дата
 +
!style="background:#ffdead;"| Первый параметр
 +
!style="background:#ffdead;"| Второй параметр
 +
|- valign="top"
 +
|Год
 +
|1 января указанного года - 31 декабря указанного года
 +
|1 января указанного года
 +
|31 декабря указанного года
 +
|- valign="top"
 +
|Месяц
 +
|1-е число указанного месяца текущего года - Последнее число указанного месяца текущего года
 +
|1-е число указанного месяца текущего года
 +
|Последнее число указанного месяца текущего года
 +
|- valign="top"
 +
|День
 +
|День текущего месяца текущего года
 +
|День текущего месяца текущего года
 +
|День текущего месяца текущего года
 +
|- valign="top"
 +
|Год и месяц
 +
|1-е число указанного месяца указанного года - Последнее число указанного месяца указанного года
 +
|1-е число указанного месяца указанного года
 +
|Последнее число указанного месяца указанного года
 +
|- valign="top"
 +
|День и месяц
 +
|День указанного месяца текущего года
 +
|День указанного месяца текущего года
 +
|День указанного месяца текущего года
 +
|- valign="top"
 +
|День недели
 +
|День, соответствующий указанному дню текущей недели
 +
|Указанный день текущей недели
 +
|Указанный день текущей недели
 +
|}
 +
 
 +
При вводе с клавиатуры и при отображении в поле ввода мы будем поддерживать только два формата даты: dd.mm.yy и dd.mm.yyyy<ref>Возможно, имеет смысл поддерживать различные форматы даты. Для конвертации из строки можно использовать одну из [http://stackoverflow.com/questions/3786823/converting-a-string-to-tdatetime-based-on-an-arbitrary-format доступных процедур].</ref>.
 +
 
 +
Исходное состояние: курсор попадает в поле ввода. Оно либо пустое, либо находящийся в нем текст выделяется, так что вводимые символы заменят его.
 +
 
 +
Пользователь начинает вводить цифры. Первые две введенные цифры трактуются как номер дня. После них автоматически подставляется разделитель. Пользователь может так же ввести одну только цифру и ввести разделитель самостоятельно. Аналогичным образом, следующие две цифры трактуются как номер месяца. Некорректные цифры просто не вводятся и не отображаются экране. Например, нельзя первой цифрой ввести 4, так как нет номера дня, начинающегося с 4-х.
 +
 
 +
Окончив ввод первой даты, пользователь набирает символ '-' и вводит вторую дату. Можно ввести только одну единственную дату, что будет соответствовать однодневному диапазону.
 +
 
 +
В любой момент пользователь может набрать метасимволы, при этом в поле ввода подставится и выделится соответствующий им диапазон. Сами метасимволы на экране не отображаются.
 +
 
 +
Нажатие пробела подставляет текущую дату. Обратите внимание на различие между пробелом и метасимволом "с" (сегодня). "с" подставит в поле ввода диапазон из одного дня, соответствующий сегодняшней дате, заменив им все содержимое поля ввода, тогда как пробел подставит в качестве одной из дат диапазона сегодняшнюю дату.
 +
 
 +
Поясним на примере. Пусть сегодня 5-е мая 2005 года. Тогда, введя в поле ввода строку "01.04.2004-" и нажав пробел, пользователь получит диапазон "01.04.2005-05.05.2005". Если же, ввести "01.04.2004-" и нажать "с", то содержимое поля ввода будет замещено значением "05.05.2005". Более того, в истории сохранится, что пользователь воспользовался метасимволом и при открытии окна на следующий день в поле автоматически подставится "06.05.2005".
 +
 
 +
=== Шорткаты ===
 +
 
 +
{| border="1" cellpadding="2" cellspacing="0" style="border-collapse:collapse;"
 +
!style="background:#ffdead;"| Русский
 +
!style="background:#ffdead;"| Английский
 +
!style="background:#ffdead;"| Значение
 +
|- valign="top"
 +
 +
|t
 +
|Сегодня
 +
|- valign="top"
 +
 +
|o
 +
|Завтра
 +
|- valign="top"
 +
 +
|y
 +
|Вчера
 +
|- valign="top"
 +
 +
|w
 +
|Текущая неделя
 +
|- valign="top"
 +
 +
|l
 +
|Прошедшая неделя
 +
|- valign="top"
 +
 +
|n
 +
|Следующая неделя
 +
|- valign="top"
 +
 +
|m
 +
|Текущий месяц
 +
|- valign="top"
 +
 +
|x
 +
|Следующий месяц
 +
|- valign="top"
 +
 +
|h
 +
|Прошедший месяц
 +
|- valign="top"
 +
 +
|q
 +
|Текущий квартал
 +
|- valign="top"
 +
 +
|r
 +
|Прошедший квартал
 +
|- valign="top"
 +
 +
|g
 +
|Следующий квартал
 +
|- valign="top"
 +
 +
|a
 +
|Текущий год
 +
|- valign="top"
 +
 +
|j
 +
|Прошедший год
 +
|- valign="top"
 +
 +
|v
 +
|Следующий год
 +
|}
 +
 
 +
Распознавание шортката не должно зависеть от режима CAPS LOCK и от нажатой клавиши Shift.
 +
 
 +
= Детали реализации =
 +
 
 +
* Имя файла: gsPeriodEdit.pas
 +
* Расположение: gedemin\component
 +
 
 +
Необходимо достигнуть максимального соответствия по свойствам и методам со стандартным компонентом [http://docwiki.embarcadero.com/VCL/en/ComCtrls.TDateTimePicker TDateTimePicker].
 +
 
 +
== Тип TgsDatePeriodKind ==
 +
 
 +
  type
 +
    TgsDatePeriodKind = (dpkYear, dpkQuarter, dpkMonth, dpkWeek, dpkDay, dpkFree);
 +
 
 +
== Класс TgsDatePeriod(TObject) ==
 +
 
 +
Предназначен для хранения, представления, конвертации и манипуляции периодом дат.
 +
 
 +
=== Свойства ===
 +
 
 +
{| border="1" cellpadding="2" cellspacing="0" style="border-collapse:collapse;"
 +
| Date: TDate || Первая дата промежутка.
 +
|-
 +
| EndDate: TDate || Последняя дата промежутка. Всегда больше либо равно Date.
 +
|-
 +
| Kind: TgsDatePeriodKind || Тип периода. По умолчанию dpkFree. При присвоении свойства проверяются значения Date и EndDate. Если они не соответствуют типу периода, то генерируется исключение EgsDatePeriod.
 +
|-
 +
| MaxDate: TDate || Максимально дозволенная дата. При выходе хотя бы одной из границ диапазона за рамки MinDate..MaxDate генерируется исключение EgsDatePeriod. По умолчанию MaxDate = 0. При MaxDate = MinDate = 0 проверка отключена.
 +
|-
 +
| MinDate: TDate || Минимально дозволенная дата. При выходе хотя бы одной из границ диапазона за рамки MinDate..MaxDate генерируется исключение EgsDatePeriod. По умолчанию MinDate = 0. При MaxDate = MinDate = 0 проверка отключена.
 +
|}
 +
 
 +
=== Методы ===
 +
 
 +
{| border="1" cellpadding="2" cellspacing="0" style="border-collapse:collapse;"
 +
|-
 +
| procedure Assign(const ASource: TgsDatePeriod) || Копирует переданный объект.
 +
|-
 +
| procedure DecodeString(const AString: String) || Декодирует строку. Присваивает границы интервала и его тип. При неверно заданном формате строки выдает исключение EgsDatePeriod.
 +
|-
 +
| function EncodeString: String || Формирует строку для отображения на экране в соответствии с типом и границами интервала.
 +
|-
 +
| function ProcessShortCut(const AShortcut: String): Boolean || Обрабатывает ShortCut. Присваивает новый диапазон дат и возвращает True. Если передан неверный шорткат, то возвращает False.
 +
|}
 +
 
 +
== Визуальный компонент TgsMultiCalendar(TWinControl) ==
 +
 
 +
=== Свойства ===
 +
 
 +
{| border="1" cellpadding="2" cellspacing="0" style="border-collapse:collapse;"
 +
|-
 +
| DatePeriod: TgsDatePeriod || Период дат.
 +
|}
 +
 
 +
== Визуальный компонент TgsCalendarEdit(TWinControl) ==
 +
 
 +
Компонент содержит TEdit для ввода периода дат и шорткатов. Справа от поля редактирования находится кнопка вызова выпадающего окна TgsMultiCalendar.
 +
 
 +
=== Свойства ===
 +
 
 +
{| border="1" cellpadding="2" cellspacing="0" style="border-collapse:collapse;"
 +
| GUID: TGUID || Уникальный ИД экземпляра компонента. См. "Сохранение истории ранее выбранных значений" ниже.
 +
|-
 +
| DatePeriod: TgsDatePeriod || Период дат.
 +
|-
 +
| Text: String || Текст, который отображается в поле ввода.
 +
|}
 +
 
 +
==== Алгоритм обработки нажатия клавиш ====
 +
 
 +
Организуем очередь из двух символов (так как у нас максимальная длина шортката два символа). При нажатии очередного символа делаем следующее:
 +
 
 +
# Если активен таймер, то удаляем его.
 +
# Преобразуем символ если он нажат на английской раскладке клавиатуры (т.е. наш компонент должен быть нечуствителен к выбранной раскладке клавиатуры).
 +
# Помещаем символ в очередь.
 +
# Если в очереди два символа, то проверяем на двухсимвольный шорткат.
 +
## Если шорткат успешно обработан, то очищаем очередь.
 +
## Если это не шорткат, то удаляем из очереди первый символ.
 +
# Если в очереди один символ, то запускаем таймер.
 +
# Передаем управление стандартному обработчику.
 +
 
 +
Когда срабатывает таймер выполняем следующий алгоритм:
 +
 
 +
# Проверяем, имеем ли мы фокус.
 +
## Если да, то проверяем сколько символов в очереди.
 +
### Если один, то проверяем его на шорткат.
 +
#### Если это шорткат, то обрабатываем и очищаем очередь.
 +
#### Если нет -- оставляем очередь как есть.
 +
# В любом случае уничтожаем таймер.
 +
 
 +
=== Сохранение истории ранее выбранных значений ===
 +
 
 +
Историю значений сохраняет и считывает компонент TgsCalendarEdit. Компонент имеет read-write published свойство GUID типа TGUID, которое присваивается:
 +
 
 +
* В конструкторе, если установлен флаг csDesigning и не установлен флаг csLoading
 +
* В методе Loaded после вызова inherited, если к этому моменту свойство пустое
 +
 
 +
При динамическом создании компонента программист обязан сам присваивать это свойство некоторому ГУИДу, если он хочет обеспечить сохранение его истории.
 +
 
 +
История ранее введенных или выбранных периодов хранится в системном реестре в ветке:
 +
 
 +
  HKEY_CURRENT_USER\Software\Golden Software\Gedemin\Client\CurrentVersion\TgsCalendarEdit
 +
 
 +
История одного компонента хранится ввиде строкового параметра, где имя параметра это GUID, а значение -- это строка вида:
 +
 
 +
  "дата_сохранения","период1","период2","период3",..."период9"
 +
 
 +
Здесь "дата_сохранения" -- это дата, когда история была записана в реестр. В дальнейшем она может быть использована для очистки реестра от неиспользуемых (устаревших) значений. Мы берем параметры в двойные кавычки чтобы избежать коллизии с запятой, которая может находиться в значении периода.
 +
 
 +
= Примечания =
 +
<references/>
 +
 
 +
[[Category:Постановка-Сделано]]
 +
 
 +
__NOTOC__

Текущая версия на 18:46, 10 апреля 2011

В большинстве случаев при построении отчета или фильтрации массива документов пользователь указывает период дат. Сейчас в Гедымине применяются два компонента ввода даты для указания начального и конечного дня периода. Предлагается реализовать простой и удобный визуальный компонент для ввода периода дат как набором с клавиатуры, так и путем выбора мышью. Минимальный период -- один день. Ввод даты окончания периода меньшей даты начала не допускается.

periodedit_1.png

Компонент должен представлять собой поле ввода TEdit справа от которого расположена кнопка для вызова выпадающего окна.

[править] Ввод периода с помощью мыши

Диапазон дат можно указать мышью в выпадающем окне следующими способами:

periodedit_2.png

Выпадающее окно разделено по вертикали на две части. В левой находится список выбора режима указания периода. В зависимости от режима справа располагается:

  • Год. Календарь для выбора года.
  • Квартал. Календарь для выбора года и квартала.
  • Месяц. Календарь для выбора года и месяца.
  • Неделя. Календарь для выбора года, месяца и недели.
  • День. Календарь для выбора года. месяца, дня.
  • Произвольный. Два календаря для выбора первого и последнего дня периода.
  • Шорт-кат. Список доступных шорт-катов.
  • История. Несколько последних периодов, выбранных пользователем.

В правой части, внизу показывается текущий период. При клике мышкой он выбирается и окно закрывается. В зависимости от режима выбора надпись имеет следующий вид:

  • Год -- "Текущий год: 2010 г."
  • Квартал -- "Текущий квартал: 4 кв. 2010 г."
  • Месяц -- "Текущий месяц: август 2010 г."
  • Неделя -- "Текущая неделя: 22 нд. 2010 г."
  • День -- "Сегодня: 22.08.2010"

В режиме выбора произвольного периода под каждым календарем выводится налпись "Сегодня: 22.08.2010". Клик по ней устанавливает на календаре текущую дату, но не закрывает компонент выбора.

После выбора периода окно закрывается. Выпадающее окно можно закрыть без выбора периода клавишей Esc, либо кликнув мышью за его пределами.

Для отображения календаря воспользуемся идеями из Windows 7.

[править] Ввод периода с помощью клавиатуры

В поле ввода пользователю предоставляется несколько вариантов ввода временного отрезка:

periodedit_3.png

Самый очевидный вариант -- ввод двух дат. Например, 01.01.2009-31.12.2009.

Полный формат даты -- когда указан день, месяц и год. Сокращенный -- если хотя бы одна из частей даты пропущена.

periodedit_4.png

Сокращенная дата Единственная дата Первый параметр Второй параметр
Год 1 января указанного года - 31 декабря указанного года 1 января указанного года 31 декабря указанного года
Месяц 1-е число указанного месяца текущего года - Последнее число указанного месяца текущего года 1-е число указанного месяца текущего года Последнее число указанного месяца текущего года
День День текущего месяца текущего года День текущего месяца текущего года День текущего месяца текущего года
Год и месяц 1-е число указанного месяца указанного года - Последнее число указанного месяца указанного года 1-е число указанного месяца указанного года Последнее число указанного месяца указанного года
День и месяц День указанного месяца текущего года День указанного месяца текущего года День указанного месяца текущего года
День недели День, соответствующий указанному дню текущей недели Указанный день текущей недели Указанный день текущей недели

При вводе с клавиатуры и при отображении в поле ввода мы будем поддерживать только два формата даты: dd.mm.yy и dd.mm.yyyy[1].

Исходное состояние: курсор попадает в поле ввода. Оно либо пустое, либо находящийся в нем текст выделяется, так что вводимые символы заменят его.

Пользователь начинает вводить цифры. Первые две введенные цифры трактуются как номер дня. После них автоматически подставляется разделитель. Пользователь может так же ввести одну только цифру и ввести разделитель самостоятельно. Аналогичным образом, следующие две цифры трактуются как номер месяца. Некорректные цифры просто не вводятся и не отображаются экране. Например, нельзя первой цифрой ввести 4, так как нет номера дня, начинающегося с 4-х.

Окончив ввод первой даты, пользователь набирает символ '-' и вводит вторую дату. Можно ввести только одну единственную дату, что будет соответствовать однодневному диапазону.

В любой момент пользователь может набрать метасимволы, при этом в поле ввода подставится и выделится соответствующий им диапазон. Сами метасимволы на экране не отображаются.

Нажатие пробела подставляет текущую дату. Обратите внимание на различие между пробелом и метасимволом "с" (сегодня). "с" подставит в поле ввода диапазон из одного дня, соответствующий сегодняшней дате, заменив им все содержимое поля ввода, тогда как пробел подставит в качестве одной из дат диапазона сегодняшнюю дату.

Поясним на примере. Пусть сегодня 5-е мая 2005 года. Тогда, введя в поле ввода строку "01.04.2004-" и нажав пробел, пользователь получит диапазон "01.04.2005-05.05.2005". Если же, ввести "01.04.2004-" и нажать "с", то содержимое поля ввода будет замещено значением "05.05.2005". Более того, в истории сохранится, что пользователь воспользовался метасимволом и при открытии окна на следующий день в поле автоматически подставится "06.05.2005".

[править] Шорткаты

Русский Английский Значение
с t Сегодня
з o Завтра
в y Вчера
н w Текущая неделя
я l Прошедшая неделя
ю n Следующая неделя
м m Текущий месяц
л x Следующий месяц
р h Прошедший месяц
к q Текущий квартал
и r Прошедший квартал
й g Следующий квартал
г a Текущий год
у j Прошедший год
т v Следующий год

Распознавание шортката не должно зависеть от режима CAPS LOCK и от нажатой клавиши Shift.

[править] Детали реализации

  • Имя файла: gsPeriodEdit.pas
  • Расположение: gedemin\component

Необходимо достигнуть максимального соответствия по свойствам и методам со стандартным компонентом TDateTimePicker.

[править] Тип TgsDatePeriodKind

 type
   TgsDatePeriodKind = (dpkYear, dpkQuarter, dpkMonth, dpkWeek, dpkDay, dpkFree);

[править] Класс TgsDatePeriod(TObject)

Предназначен для хранения, представления, конвертации и манипуляции периодом дат.

[править] Свойства

Date: TDate Первая дата промежутка.
EndDate: TDate Последняя дата промежутка. Всегда больше либо равно Date.
Kind: TgsDatePeriodKind Тип периода. По умолчанию dpkFree. При присвоении свойства проверяются значения Date и EndDate. Если они не соответствуют типу периода, то генерируется исключение EgsDatePeriod.
MaxDate: TDate Максимально дозволенная дата. При выходе хотя бы одной из границ диапазона за рамки MinDate..MaxDate генерируется исключение EgsDatePeriod. По умолчанию MaxDate = 0. При MaxDate = MinDate = 0 проверка отключена.
MinDate: TDate Минимально дозволенная дата. При выходе хотя бы одной из границ диапазона за рамки MinDate..MaxDate генерируется исключение EgsDatePeriod. По умолчанию MinDate = 0. При MaxDate = MinDate = 0 проверка отключена.

[править] Методы

procedure Assign(const ASource: TgsDatePeriod) Копирует переданный объект.
procedure DecodeString(const AString: String) Декодирует строку. Присваивает границы интервала и его тип. При неверно заданном формате строки выдает исключение EgsDatePeriod.
function EncodeString: String Формирует строку для отображения на экране в соответствии с типом и границами интервала.
function ProcessShortCut(const AShortcut: String): Boolean Обрабатывает ShortCut. Присваивает новый диапазон дат и возвращает True. Если передан неверный шорткат, то возвращает False.

[править] Визуальный компонент TgsMultiCalendar(TWinControl)

[править] Свойства

DatePeriod: TgsDatePeriod Период дат.

[править] Визуальный компонент TgsCalendarEdit(TWinControl)

Компонент содержит TEdit для ввода периода дат и шорткатов. Справа от поля редактирования находится кнопка вызова выпадающего окна TgsMultiCalendar.

[править] Свойства

GUID: TGUID Уникальный ИД экземпляра компонента. См. "Сохранение истории ранее выбранных значений" ниже.
DatePeriod: TgsDatePeriod Период дат.
Text: String Текст, который отображается в поле ввода.

[править] Алгоритм обработки нажатия клавиш

Организуем очередь из двух символов (так как у нас максимальная длина шортката два символа). При нажатии очередного символа делаем следующее:

  1. Если активен таймер, то удаляем его.
  2. Преобразуем символ если он нажат на английской раскладке клавиатуры (т.е. наш компонент должен быть нечуствителен к выбранной раскладке клавиатуры).
  3. Помещаем символ в очередь.
  4. Если в очереди два символа, то проверяем на двухсимвольный шорткат.
    1. Если шорткат успешно обработан, то очищаем очередь.
    2. Если это не шорткат, то удаляем из очереди первый символ.
  5. Если в очереди один символ, то запускаем таймер.
  6. Передаем управление стандартному обработчику.

Когда срабатывает таймер выполняем следующий алгоритм:

  1. Проверяем, имеем ли мы фокус.
    1. Если да, то проверяем сколько символов в очереди.
      1. Если один, то проверяем его на шорткат.
        1. Если это шорткат, то обрабатываем и очищаем очередь.
        2. Если нет -- оставляем очередь как есть.
  2. В любом случае уничтожаем таймер.

[править] Сохранение истории ранее выбранных значений

Историю значений сохраняет и считывает компонент TgsCalendarEdit. Компонент имеет read-write published свойство GUID типа TGUID, которое присваивается:

  • В конструкторе, если установлен флаг csDesigning и не установлен флаг csLoading
  • В методе Loaded после вызова inherited, если к этому моменту свойство пустое

При динамическом создании компонента программист обязан сам присваивать это свойство некоторому ГУИДу, если он хочет обеспечить сохранение его истории.

История ранее введенных или выбранных периодов хранится в системном реестре в ветке:

 HKEY_CURRENT_USER\Software\Golden Software\Gedemin\Client\CurrentVersion\TgsCalendarEdit

История одного компонента хранится ввиде строкового параметра, где имя параметра это GUID, а значение -- это строка вида:

 "дата_сохранения","период1","период2","период3",..."период9"

Здесь "дата_сохранения" -- это дата, когда история была записана в реестр. В дальнейшем она может быть использована для очистки реестра от неиспользуемых (устаревших) значений. Мы берем параметры в двойные кавычки чтобы избежать коллизии с запятой, которая может находиться в значении периода.

[править] Примечания

  1. Возможно, имеет смысл поддерживать различные форматы даты. Для конвертации из строки можно использовать одну из доступных процедур.
Персональные инструменты
Пространства имён

Варианты
Действия
Навигация
Инструменты