Obx/Docu/ru/Scroll.odc

Описание системы примерами: ObxScroll
(C) Перевод на русский язык: Чернышов Л. Н., 2005.

По умолчанию, отображение (view) всегда отображается в полном размере, где предпочтительный размер может быть определен через  сообщение Properties.SizePref. Однако, иногда содержимое отображения слишком велико, чтобы быть показанным полностью, и поэтому должна поддерживаться прокрутка содержимого отображения в пределах ее рамки. Пример отображений, которые поддерживают прокрутку, - тексты.

Имеется универсальный механизм для реализации прокрутки - простое изменение начала координат прокручиваемой рамки. Стандартный контейнер документа использует эту особенность. Каждое отображение, которое открыто в своем собственном окне, содержится в контейнере документа, поэтому универсальный механизм доступен каждому корневому отображению. Тот же самый механизм можно предложить и для внедренных картинок с использованием оболочки, которая попиксельно прокручивает рамку отображения. Однако, если вы хотите поддержать более сложное поведение программы, чем попиксельная прокрутка, или если эффективная реализация картинки зависит от поддержания рамок меньших размеров, то необходима явная обработка прокрутки.

В этом примере мы описываем механизм ("протокол"), который отображение должно реализовать для поддержания прокрутки. Как пример мы представляем отображение шахматной доски 10x10 (см. рис.1), которое может быть прокручено в пределах ее рамки. Если это отображение прокручивается линия за линией, то картинка отображается поле за полем. Кроме того, это отображение также может быть прокручено, если оно вложено в любой контейнер с полосами прокрутки. Для того, чтобы прокручивать внедренное отображение, оно должно быть в фокусе, при этом необходимо удерживать клавишу Ctrl, когда курсор находится на полосе прокрутки.




Рис.1
							
Если отображение хочет поддержива прокрутку, она должна хранить текущее положение прокрутки в своих переменных. В нашем примере координаты верхнего левого поля (например, (6,2)) описывают положение прокрутки. Когда картинка восстанавливается, только видимые поля должны быть отрисованы.

Чтобы опросить текущее состояние прокрутки, каркас (framework) посылает отображению запрос Controllers.PollSectionMsg. По возвращенной отображением информации определяется появление полос прокрутки. В этом сообщении wholeSize обозначает ширину или высоту содержимого отображения в произвольных координатах, а partSize описывает ширину или высоту самого отображения в тех же самых координатах (то есть, размер отображения по сравнению с его содержимым). Последнее значение используется для определения размера бегунка в полосе прокрутки (изменяющийся размер бегунка поддерживается не всеми оконными системами (в Windows - поддерживается, прим. перев.)). Позиция бегунка в пределах полосы прокрутки определяется согласно значению поля partPos, которое определяет начало координат отображения. Значение partPos должно быть больше или равно нулю и меньше или равно разности между полным размером и размером видимой части.

В нашем примере все эти значения определены в терминах строк или столбцов. partSize устанавливается в ширину или высоту отображения, разделенную на ширину или высоту одного поля, а partPos установливается равной координате верхнего левого поля. Для приведенного выше примера отображения размер видимой части равен четырем. Значение wholeSize зависит от позиции прокрутки. Если размер части является меньшим, чем разность между размером доски и позицией видимой части, то wholeSize устанавливается в 10, то есть в размер доски. Иначе, если размер части больше, чем видимые поля шахматной доски, это пустое пространство нужно добавить к общему размеру отображения. Последняя ситуация может произойти, если размер отображения увеличен, поскольку позиция прокрутки не изменяется, если при изменении размера отображения.

Когда отображение прокручивается, ему отправляется сообщение Properties.ScrollMsg. Это сообщение определяет, должна ли быть выполнена операция горизонтальной или вертикальной прокрутки, а также определяет, должно ли быть отображение прокручено приращениями или декрементами построчно или постранично, или должно быть прокручена до некой абсолютной позиции. Здесь мы снова должны заметить, что отображение не прокручивается вне его рамки. Если выполняется абсолютная прокрутка, то позиция, до которой будет произведена прокрутка, определяется в тех же самых координатах, которые использует PollSectionMsg.

Все прочие методы в исходном тексте вполне понятны. Метод CopyFrom необходим, чтобы инициализировать копию картинки с той же самой позицией прокрутки, а методы Externalize и Internalize позволяют сохранять позицию прокрутки. Обратите внимание, что позиция прокрутки сохраняется только для внедренных картинок. Для корневых картинок, позиция прокрутки нормализуется при сохранении, то есть устанавливатся в (0, 0). Должно ли отображение нормализовать свое сохраняемое состояние, проверяется функцией Normalize, которая определена в контексте отображения. При сохранении внедренные отображения сохраняют свою текущую позицию прокрутки, то есть, позиция прокрутки не нормализуется.

Наконец, метод HandlePropMsg определяет заданный по умолчанию размер вновь созданного отображения (в зависимости от его позиции прокрутки); он определяет желание отображения получать фокус ввода (иначе внедренные шахматные картинки не могли бы быть прокручены); и он указывает, что размер корневых отображений автоматически подогнан под размер окна.

Команды Deposit и DepositAt создают и размещают в очереди новое отображение. Если позиция прокрутки - (x, y), то по умолчанию ширина отображения = (10-x)*(размер ячейки), а высота = (10-y)*(размер ячейки).

Возможны дальнейшие усовершенствования этого примера. Например, операции прокрутки могли быть реализованы как подлинные операции, которые могут быть отменены. Обратите внимание однако, что эти операции должны быть отменяемыми только для отображений, которые не внедрены в корневой контекст. Используйте метод контекста Normalize, чтобы определять, должны операции быть отменяемыми или нет.

 "ObxScroll.Deposit; StdCmds.Open"

ObxScrollsources