// // Brian's Theme (Object-oriented version) // --------------------------------------- // This version copyright (c) 1996-1998 by Lachlan Patrick. // Written using GraphApp. // // This is a complex example not for beginners. It makes use of // the timer functions, colour, windows and keyboard call-backs. // #include #include #include #include // // Define the class: // class BriansTheme { public: int width, height; int banner_height; char * banner; window win; int step_size; int step_location; point origin; rgb colour; BriansTheme(); int random(int max); void change_location(); void handle_mouse(int buttons, point xy); void handle_keydown(int key); void draw_window(rect r); void resize_window(rect r); void init_window(); }; BriansTheme brian; // // Class constructor: // BriansTheme :: BriansTheme () { width = 400; height = 240; banner_height = 40; banner = "0-9 for step size, Q to stop, R,G,B,C,M,Y,K for colours."; win = NULL; step_size = 3; step_location = 0; origin = pt(0,0); colour = Blue; } // // Class functions: // int BriansTheme :: random(int max) { return (rand() % max); } void BriansTheme :: change_location() { BriansTheme *self = (BriansTheme *) this; self->origin.x = self->random(self->width); self->origin.y = self->random(self->height); self->step_location = 0; } void BriansTheme :: handle_mouse(int buttons, point xy) { BriansTheme *self = (BriansTheme *) getdata((window)this); self->origin = xy; self->step_location = 0; redraw(self->win); } void BriansTheme :: handle_keydown(int key) { BriansTheme *self = (BriansTheme *) getdata((window)this); if (isdigit(key)) self->step_size = key - '0'; else if ((key == 'q') || (key == 'Q') || (key == ESC)) exitapp(); else switch (tolower(key)) { case 'r': self->colour = Red; break; case 'g': self->colour = Green; break; case 'b': self->colour = Blue; break; case 'c': self->colour = Cyan; break; case 'm': self->colour = Magenta; break; case 'y': self->colour = Yellow; break; case 'k': self->colour = Black; break; default: break; } } void BriansTheme :: draw_window(rect r) { BriansTheme *self = (BriansTheme *) getdata((window)this); if (self->banner_height > 0) { r.y = self->height; r.height = self->banner_height; setcolour(Black); drawtext(r, Center + VCenter, self->banner); } } void BriansTheme :: resize_window(rect r) { BriansTheme *self = (BriansTheme *) getdata((window)this); self->banner_height = getheight(SystemFont) * 2 + 8; if (r.height < 4 * self->banner_height) // too small for banner self->banner_height = 0; self->height = r.height - self->banner_height; self->width = r.width; self->change_location(); } // Create and display the window: void BriansTheme :: init_window() { BriansTheme *self = (BriansTheme *) this; self->banner_height = getheight(SystemFont) * 2 + 8; self->win = newwindow("Brian's Theme", rect(0,0,self->width,self->height+self->banner_height), StandardWindow | Centered ); setdata(self->win, this); setmouseup(self->win, (mousefn) self->handle_mouse); setkeydown(self->win, (keyfn) self->handle_keydown); setredraw(self->win, (drawfn) self->draw_window); setresize(self->win, (drawfn) self->resize_window); show(self->win); } // Non-class functions: void draw_and_step(void *data) { BriansTheme *self = (BriansTheme *) data; drawto(self->win); setcolour(self->colour); if (self->step_location <= self->height) { drawline(self->origin, pt(0, self->height-self->step_location)); drawline(self->origin, pt(self->width, self->step_location)); } if (self->step_location <= self->width) { drawline(self->origin, pt(self->step_location, 0)); drawline(self->origin, pt(self->width - self->step_location, self->height)); } self->step_location = self->step_location + self->step_size; if ((self->step_location > self->width+100) && (self->step_location > self->height+100)) { self->change_location(); redraw(self->win); } } void main() { initapp(0,0); brian.init_window(); settimerfn(draw_and_step, &brian); settimer(80); mainloop(); }