Главная страница Случайная страница КАТЕГОРИИ: АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
Пример кода.
Класс Window (WindowImp) определяет абстракцию окна для клиентских приложений:
class Window { public: Window(View* contents); // запросы, обрабатываемые окном virtual void DrawContents(); virtual void Open(); virtual void Close(); virtual void Iconify(), virtual void Deiconify(); // запросы, перенаправляемые реализации virtual void SetOrigin(const Point& at); virtual void SetExtent(const Point& extent); virtual void Raise(); virtual void Lower(); virtual void DrawLine(const Point&, const Point&); virtual void DrawRect(const Point&, const Point&); virtual void DrawPolygon(const Point[], int n); virtual void DrawText(const char*, const Point&); protected: Windowlmp* GetWindowImp(); View* GetView(); private: Windowlmp* _imp; View* _contents; // содержимое окна };
В классе Window хранится ссылка на Windowlmp - абстрактный класс, в котором объявлен интерфейс к данной оконной системе:
class Windowlmp { public: virtual void ImpTop() = 0; virtual void ImpBottom() = 0; virtual void ImpSetExtent(const Point&) = 0; virtual void ImpSetOrigin(const Point&) = 0;
virtual void DeviceRect(Coord, Coord, Coord, Coord) = 0; virtual void DeviceText(const char*, Coord, Coord) = 0; virtual void DeviceBitmap(const char*, Coord, Coord) = 0; // множество других функций для рисования в окне... protected: Windowlmp(); };
Подклассы Window определяют различные виды окон, как то: окно приложения, пиктограмма, временное диалоговое окно, плавающая палитра инструментов и т.д.
Например, класс ApplicationWindow реализует операцию DrawContents для отрисовки содержимого экземпляра класса View, который в нем хранится:
class ApplicationWindow: public Window { public: //... virtual void DrawContents(); };
void ApplicationWindow:: DrawContents () { GetView() -> DrawOn(this); }
А в классе IconWindow содержится имя растрового изображения для пиктограммы
class IconWindow: public Window { public: //... virtual void DrawContents(); private: const char* _bitmapName; };
и реализация операции DrawContents для рисования этого изображения в окне:
void IconWindow:: DrawContents() { Windowlmp* imp = GetWindowImp(); if (imp! = 0) { imp-> DeviceBitmap(_bitmapName, 0.0, 0.0); } }
Могут существовать и другие разновидности класса Window. Окну класса TransientWindow иногда необходимо как-то сообщаться с создавшим его окном во время диалога, поэтому в объекте класса хранится ссылка на создателя. Окно класса PaletteWindow всегда располагается поверх других. Окно класса ZconDockWindow (контейнер пиктограмм) хранит окна класса IconWindow и располагает их в ряд.
Операции класса Window определены в терминах интерфейса Windowlmp. Например, DrawRect вычисляет координаты по двум своим параметрам Point перед тем, как вызвать операцию Windowlmp, которая рисует в окне прямоугольник:
void Window:: DrawRect (const Point& pi, const Point& p2) { Windowlmp* imp = GetWindowImp (); imp-> DeviceRect(pl.X(), pl.Y(), p2.X(), p2.Y()); }
Конкретные подклассы Windowlmp поддерживают разные оконные системы. Так, класс XWindowImp ориентирован на систему X Window:
class XWindowImp: public Windowlmp { public: XWindowImp(); virtual void DeviceRect(Coord, Coord, Coord, Coord);
// прочие операции открытого интерфейса... private:
// переменные, описывающие специфичное для X Window состояние, // в том числе: Display* _dpy; Drawable _winid; // идентификатор окна GC _gc; // графический контекст окна };
Для Presentation Manager (РМ) мы определяем класс PMWindowImp:
class PMWindowImp: public Windowlmp { public: PMWindowImp (); virtual void DeviceRect(Coord, Coord, Coord, Coord); // прочие операции открытого интерфейса... private: // переменные, описывающие специфичное для РМ Window состояние, // в том числе: HPS _hps; };
Эти подклассы реализуют операции Windowlmp в терминах примитивов оконной системы. Например, DeviceRect для X Window реализуется так:
void XWindowImp:: DeviceRect ( Coord x0, Coord y0, Coord xl, Coord yl) { int x = round(min(x0, x l)); int у = rpund(min(y0, yl)); int w = round(abs(x0 - x l)); int h = round(abs(y0 - y l)); XDrawRectangle(_dpy, _winid, _gc, x, y, w, h); }
А для РМ - так:
void PMWindowImp:: DeviceRect (Coord x0, Coord y0, Coord xl, Coord yl) { Coord left = min(x0, xl); Coord right = max(x0, xl); Coord bottom = min(y0, yl); Coord top = max(y0, yl); PPOINTL point[4];
point[0].x = left; point[0].у = top; point[1].x = right; point[1].у = top; point[2].x = right; point[2].у = bottom; point[3].x = left; point[3].у = bottom; if ( (GpiBeginPath(_hps, 1L) = = false) || (GpiSetCurrentPosition(_hps, & point[3]) = = false) || (GpiPolyLine(_hps, 4L, point) == GPI_ERROR) || (GpiEndPath(_hps) == false)) { // сообщить об ошибке } else { GpiStrokePath(_hps, 1L, 0L); } }
Как окно получает экземпляр нужного подкласса Windowlmp? В данном примере мы предположим, что за это отвечает класс Window. Его операция GetWindowImp получает подходящий экземпляр от абстрактной фабрики, которая инкапсулирует все зависимости от оконной системы.
Windowlmp* Window:: GetWindowImp () { if (_imp == 0) { _imp = WindowSystemFactory:: Instance() -> MakeWindowImp(); } return _imp;
WindowSystemFactory:: Instance () возвращает абстрактную фабрику, которая изготавливает все системно-зависимые объекты. Для простоты мы сделали эту фабрику одиночкой и позволили классу Window обращаться к ней напрямую.
|