читатели сами в ней разберутся. В частности, можно просто ввести запрос “RGB color” в поисковую веб-машину. Среди прочих вы получите ссылки www.hyperso-lutions.org/rgb.html и www.pitt.edu/~nisg/cis/web/cgi/rgb.html. См. также упр. 13 и 14.
Обратите внимание на конструкторы класса Color, позволяющие создавать объекты как из объектов типа Color_type, так и из обычных чисел типа int. Каждый конструктор инициализирует член c. Вы можете возразить, что переменная c названа слишком коротко и непонятно, но, поскольку она используется в очень небольшой части класса Color и не предназначена для широкого использования, это не является недостатком. Мы поместили член c в закрытый раздел, чтобы защитить его от непосредственного обращения пользователей. Для представления члена c мы используем тип Fl_Color, определенный в библиотеке FLTK, который хотели бы скрыть от пользователей. Однако очень часто этот тип интерпретируется как целочисленное представление значения RGB (или другого значения), поэтому на этот случай мы предусмотрели функцию as_int(). Обратите внимание на то, что функция as_int() является константной функцией-членом, поскольку она не изменяет объект класса Color, который ее использует.
Прозрачность задается членом v, который может принимать значения Color::visible и Color::invisible, имеющие очевидный смысл. Вы можете удивиться: зачем нужен “невидимый цвет”. Оказывается, он может быть очень полезен для того, чтобы скрыть часть фигуры на экране.
13.5. Класс Line_style
Нарисовав на экране несколько линий, мы можем различать их по цвету, стилю или по обоим этим признакам. Стиль линии — это шаблон, задающий ее внешний вид. Класс Line_style используется приблизительно так:
grid.set_style(Line_style::dot);
Эта инструкция выводит на экран линии, заданные в объекте grid, как последовательность точек, а не как сплошную линию.
Это сделает сетку немного тоньше, зато более незаметной. Настраивая ширину (толщину) линий, можем придать сетке требуемый вид.
Класс Line_style выглядит так:
struct Line_style {
enum Line_style_type {
solid=FL_SOLID, // -------
dash=FL_DASH, // - - - -
dot=FL_DOT, // .......
dashdot=FL_DASHDOT, // - . - .
dashdotdot=FL_DASHDOTDOT, // -..-..
};
Line_style(Line_style_type ss):s(ss), w(0) { }
Line_style(Line_style_type lst, int ww):s(lst), w(ww) { }
Line_style(int ss):s(ss), w(0) { }
int width() const { return w; }
int style() const { return s; }
private:
int s;
int w;
};
Методы программирования, использованные для определения класса Line_style, ничем не отличаются от методов, использованных для класса Color. Здесь мы снова скрываем тот факт, что для представления стилей линии библиотека FKTK использует тип int. Почему стоит скрывать эту информацию? Потому что эти способы представления при модификации библиотеки могут измениться. В следующей версии библиотеки FLTK может появиться тип Fl_linestyle, да и мы сами можем перенастроить наш интерфейс на другую библиотеку. В любом случае не стоит замусоривать свой код переменными типа int только потому, что мы знаем, как они задают стиль линий.
Как правило, мы не заботимся о стиле вообще; мы просто полагаемся на параметры, заданные по умолчанию (сплошные линии, ширина которых задана по умолчанию). Если мы не указываем ширину линии явно, то она задается конструктором. Установка значений по умолчанию — это одно из предназначений конструктора, а правильно выбранные значения, задаваемые по умолчанию, могут значительно облегчить работу пользователей.
Класс Line_style состоит из двух “компонентов”: характеристики стиля (например, пунктирные или сплошные линии) и ширины (толщина линий). Ширина измеряется в целых числах. По умолчанию ширина равна единице. Если нам нужна более широкая линия, то ее толщину можно задать следующим образом:
grid.set_style(Line_style(Line_style::dash,2));
В итоге получим следующее изображение:
Обратите внимание на то, что цвет и стиль относятся ко всем линиям, образующим фигуру. Это одно из преимуществ группирования нескольких линий в один графический объект, например класса Lines, Open_polyline или Polygon. Если мы хотим управлять цветом или стилем линий по отдельности, то их следует задать как отдельные объекты класса Line. Рассмотрим пример.
horizontal.set_color(Color::red);
vertical.set_color(Color::green);
На экране откроется окно, приведенное ниже.
13.6. Класс Open_polyline
Класс Open_polyline определяет фигуру, состоящую из ряда отрезков линий, соединенных между собой и заданных последовательностью точек. Слово poly имеет греческое происхождение и означает “много”, а polyline — это удобное имя для фигуры, состоящей из многих линий. Рассмотрим пример.
Open_polyline opl;
opl.add(Point(100,100));
opl.add(Point(150,200));
opl.add(Point(250,250));
opl.add(Point(300,200));
Этот фрагмент кода создает фигуру, которую можно нарисовать, соединяя следующие точки.
В принципе Open_polyline — это выдуманное слово, которое мы позаимствовали из детской игры “Connect the Dots” (“Соедини точки”).
Класс Open_polyline определен следующим образом:
struct Open_polyline:Shape { // открытая последовательность линий
void add(Point p) { Shape::add(p); }
};
Да-да, это все определение. В нем практически ничего нет, кроме указания имени класса и того факта, что он является наследником класса Shape. Функция add() класса Open_polyline просто позволяет пользователям получить доступ к функции add() из класса Shape (т.е. Shape::add()). Нам даже не нужно определять функцию draw_lines(), так как класс Shape по умолчанию интерпретирует добавленные точки как последовательность линий, соединенных друг с другом.
13.7. Класс Closed_polyline
Класс Closed_polyline похож на класс Open_polyline, за исключением того, что последняя точка соединяется с первой. Например, можно было бы создать объект класса Closed_polyline из тех же точек, из которых был построен объект класса Open_polyline в разделе 13.6.
Closed_polyline cpl;
cpl.add(Point(100,100));
cpl.add(Point(150,200));
cpl.add(Point(250,250));
cpl.add(Point(300,200));
Как и ожидалось, результат идентичен тому, что мы получили в разделе 13.6, за исключением последнего отрезка.
Определение класса Closed_polyline приведено ниже.
struct Closed_polyline:Open_polyline { // замкнутый ряд линий
void draw_lines() const;
};
void Closed_polyline::draw_lines() const
{
Open_polyline::draw_lines(); // сначала рисуем открытый ряд линий,
// затем