home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / i / iv26_w_3.zip / EXAMPLES / GRAPHICS / GRAPHICS.C next >
C/C++ Source or Header  |  1992-03-27  |  12KB  |  365 lines

  1. /*
  2.  * Persistent structured graphics demonstration program.
  3.  */
  4.  
  5. #include <InterViews/bitmap.h>
  6. #include <InterViews/frame.h>
  7. #include <InterViews/graphic.h>
  8. #include <InterViews/panner.h>
  9. #include <InterViews/raster.h>
  10. #include <InterViews/rubrect.h>
  11. #include <InterViews/sensor.h>
  12. #include <InterViews/tray.h>
  13. #include <InterViews/world.h>
  14. #include <InterViews/Graphic/damage.h>
  15. #include <InterViews/Graphic/ellipses.h>
  16. #include <InterViews/Graphic/grblock.h>
  17. #include <InterViews/Graphic/label.h>
  18. #include <InterViews/Graphic/lines.h>
  19. #include <InterViews/Graphic/picture.h>
  20. #include <InterViews/Graphic/polygons.h>
  21. #include <InterViews/Graphic/rasterrect.h>
  22. #include <InterViews/Graphic/splines.h>
  23. #include <InterViews/Graphic/stencil.h>
  24. #include <string.h>
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27.  
  28. /*
  29.  * Graphics class defines and implements the outer-level interactor for
  30.  * the application.  An instance of Graphic is inserted into the world.
  31.  */
  32. class Graphics : public MonoScene {
  33. public:
  34.     Graphics();
  35. protected:
  36.     Picture* InitPicture();
  37. };
  38.  
  39. /*
  40.  * View is a GraphicBlock with its Handle member function redefined to detect
  41.  * hits on the Graphic objects it contains.
  42.  */
  43. class View : public GraphicBlock {
  44. public:
  45.     View(Graphic*);
  46.     virtual ~View();
  47.  
  48.     void Move(Graphic*, Event&);
  49.     void Scale(Graphic*, Event&);
  50.     void Rotate(Graphic*, Event&);
  51.  
  52.     virtual void Handle(Event&);
  53.     virtual void Update();
  54. protected:
  55.     virtual void Draw();
  56.     virtual void Resize();
  57. private:
  58.     void Track(Event&, Rubberband&);
  59. protected:
  60.     Damage* damage;
  61. };
  62.  
  63. /* Persistent object initialization routines *********************************/
  64.  
  65. /*
  66.  * Persistent object creation function that creates an instance of any
  67.  * persistent object used in the application, given a ClassId.  A pointer
  68.  * to this function is passed to the object manager constructor.
  69.  *
  70.  * In this program, we don't derive any new classes from Persistent, so
  71.  * GraphicsConstruct simply calls GraphicConstruct. (We could have eliminated
  72.  * GraphicsConstruct altogether and simply passed a pointer to GraphicConstruct
  73.  * to the object manager constructor.)
  74.  */
  75. Persistent* GraphicsConstruct (ClassId id) {
  76.     switch (id) {
  77.     // id's of newly derived persistent classes would be cased here, e.g.:
  78.     // case DERIVED_PERSISTENT_ID_NUMBER:   return new DerivedPersistent;
  79.     default: {
  80.         return GraphicConstruct(id);
  81.     }
  82.     }
  83. }
  84.  
  85. Coord x[] = { 50, 100, 75, 100,  50,  0 };
  86. Coord y[] = {  0,  50, 75, 100, 125, 25 };
  87.  
  88. static const unsigned iv_width = 53;
  89. static const unsigned iv_height = 53;
  90. static char iv_bits[] = {
  91.    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  92.    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  93.    0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x0f,
  94.    0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
  95.    0xfe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x0f, 0xff, 0xff, 0xe0,
  96.    0xff, 0x1f, 0xfe, 0x0f, 0xff, 0xff, 0xe0, 0xff, 0x1f, 0xfe, 0x0f, 0xff,
  97.    0xff, 0xe0, 0xff, 0x1f, 0xfe, 0x0f, 0xff, 0xff, 0xe0, 0xff, 0x1f, 0xfe,
  98.    0x0f, 0x0f, 0xf8, 0xe0, 0x03, 0x1e, 0xfe, 0x0f, 0x0f, 0xfc, 0xe0, 0x07,
  99.    0x1e, 0xfe, 0x0f, 0x0f, 0x3e, 0x80, 0x0f, 0x1e, 0xfe, 0x0f, 0x0f, 0x7c,
  100.    0xc0, 0x07, 0x1e, 0xfe, 0x0f, 0x0f, 0xf8, 0xe0, 0x03, 0x1e, 0xfe, 0x0f,
  101.    0x4f, 0xf0, 0xf1, 0x41, 0x1e, 0xfe, 0x0f, 0xef, 0xe0, 0xfb, 0xe0, 0x1e,
  102.    0xfe, 0x0f, 0xff, 0xc1, 0x7f, 0xf0, 0x1f, 0xfe, 0x0f, 0xff, 0x83, 0x3f,
  103.    0xf8, 0x1f, 0xfe, 0x0f, 0xff, 0x07, 0x1f, 0xfc, 0x1f, 0xfe, 0x0f, 0xbf,
  104.    0x0f, 0x0e, 0xbe, 0x1f, 0xfe, 0x0f, 0x3f, 0x1f, 0x04, 0x9f, 0x1f, 0xfe,
  105.    0x0f, 0x00, 0x3e, 0x80, 0x0f, 0x00, 0xfe, 0x0f, 0x00, 0x7c, 0xc0, 0x07,
  106.    0x00, 0xfe, 0x0f, 0x00, 0xf8, 0xe0, 0x03, 0x00, 0xfe, 0x0f, 0x00, 0x7c,
  107.    0xc0, 0x07, 0x00, 0xfe, 0x0f, 0x00, 0x3e, 0x80, 0x0f, 0x00, 0xfe, 0x0f,
  108.    0x3f, 0x1f, 0x04, 0x9f, 0x1f, 0xfe, 0x0f, 0xbf, 0x0f, 0x0e, 0xbe, 0x1f,
  109.    0xfe, 0x0f, 0xff, 0x07, 0x1f, 0xfc, 0x1f, 0xfe, 0x0f, 0xff, 0x83, 0x3f,
  110.    0xf8, 0x1f, 0xfe, 0x0f, 0xff, 0xc1, 0x7f, 0xf0, 0x1f, 0xfe, 0x0f, 0xef,
  111.    0xe0, 0xfb, 0xe0, 0x1e, 0xfe, 0x0f, 0x4f, 0xf0, 0xf1, 0x41, 0x1e, 0xfe,
  112.    0x0f, 0x0f, 0xf8, 0xe0, 0x03, 0x1e, 0xfe, 0x0f, 0x0f, 0x7c, 0xc0, 0x07,
  113.    0x1e, 0xfe, 0x0f, 0x0f, 0x3e, 0x80, 0x0f, 0x1e, 0xfe, 0x0f, 0x0f, 0xfc,
  114.    0xe0, 0x07, 0x1e, 0xfe, 0x0f, 0x0f, 0xf8, 0xe0, 0x03, 0x1e, 0xfe, 0x0f,
  115.    0xff, 0xff, 0xe0, 0xff, 0x1f, 0xfe, 0x0f, 0xff, 0xff, 0xe0, 0xff, 0x1f,
  116.    0xfe, 0x0f, 0xff, 0xff, 0xe0, 0xff, 0x1f, 0xfe, 0x0f, 0xff, 0xff, 0xe0,
  117.    0xff, 0x1f, 0xfe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x0f, 0x00,
  118.    0x00, 0x00, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
  119.    0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff,
  120.    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  121.    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
  122. };
  123.  
  124. static Raster* CreateRaster () {
  125.     const int w = 8;
  126.     const int h = 8;
  127.     const ColorIntensity limit = 65535;
  128.     const ColorIntensity iinc = limit/w - 1;
  129.     const ColorIntensity jinc = limit/h - 1;
  130.     const ColorIntensity kinc = limit/(w*h) - 1;
  131.  
  132.     Color* color[64];
  133.     int k = 0;
  134.  
  135.     for (int i = 1; i <= w; ++i) {
  136.     for (int j = 1; j <= h; ++j) {
  137.         color[k++] = new Color(i*iinc, j*jinc, limit - k*kinc);
  138.     }
  139.     }
  140.  
  141.     return new Raster(color, w, h);
  142. }
  143.  
  144. /*
  145.  * Primordial root object creation and initialization function.  A pointer
  146.  * to this function is passed to the object manager constructor.
  147.  */
  148. void GraphicsInitialize (RefList* root) {
  149.     Picture* pict = new Picture;
  150.     FullGraphic dfault;
  151.  
  152.     InitPPaint();
  153.     root->Append(new RefList(pict));
  154.  
  155.     dfault.FillBg(true);
  156.     dfault.SetColors(pblack, pwhite);
  157.     dfault.SetPattern(psolid);
  158.     dfault.SetBrush(psingle);
  159.     dfault.SetFont(pstdfont);
  160.  
  161.     Line* line = new Line (0, 0, 75, 75, &dfault);
  162.     MultiLine* multiline = new MultiLine (x, y, 6, &dfault);
  163.     BSpline* spline = new BSpline (x, y, 6, &dfault);
  164.     Rect* rect = new Rect (0, 0, 100, 100, &dfault);
  165.     GFillRect* frect = new GFillRect (0, 0, 100, 100, &dfault);
  166.     Circle* circle = new Circle (0, 0, 50, &dfault);
  167.     FillCircle* fcircle = new FillCircle (0, 0, 50, &dfault);
  168.     GPolygon* poly = new GPolygon (x, y, 6, &dfault);
  169.     FillPolygon* fpoly = new FillPolygon (x, y, 6, &dfault);
  170.     ClosedBSpline* cspline = new ClosedBSpline (x, y, 6, &dfault);
  171.     FillBSpline* fspline = new FillBSpline (x, y, 6, &dfault);
  172.     Label* label = new Label ("Type 'q' to quit this program.", &dfault);
  173.     Stencil* stencil = new Stencil(
  174.     new Bitmap(iv_bits, iv_width, iv_height), nil, &dfault
  175.     );
  176.     RasterRect* raster = new RasterRect(CreateRaster(), &dfault);
  177.  
  178.     line->Translate(0, 300);
  179.     multiline->Translate(100, 300);
  180.     spline->Translate(250, 300);
  181.     rect->Translate(100, 150);
  182.     frect->Translate(100, 0);
  183.     circle->Scale(1.0, 0.6);
  184.     circle->Translate(0, 150);
  185.     fcircle->Scale(1.0, 0.6);
  186.     poly->Translate(250, 150);
  187.     fpoly->Translate(250, 0);
  188.     cspline->Translate(400, 150);
  189.     fspline->Translate(400, 0);
  190.     label->Translate(350, 175);
  191.     stencil->Translate(400, 300);
  192.     raster->Scale(5, 5);
  193.     raster->Translate(350, 350);
  194.  
  195.     pict->Append(line, multiline, spline, rect);
  196.     pict->Append(frect, circle, fcircle, poly);
  197.     pict->Append(fpoly, cspline, fspline, label);
  198.     pict->Append(stencil, raster);
  199. }
  200.  
  201. /* Implementation of Graphics class ******************************************/
  202.  
  203. Graphics::Graphics () {
  204.     Picture* pict = InitPicture();
  205.     View* view = new View(pict);
  206.     Tray* interior = new Tray(view);
  207.     Frame* pannerFrame = new Frame(new Panner(view));
  208.  
  209.     interior->Align(BottomRight, pannerFrame);
  210.     interior->Propagate(false);  // keep pannerFrame from changing entire view
  211.     Insert(interior);
  212. }
  213.  
  214. Picture* Graphics::InitPicture () {
  215.     TheManager = new ObjectMan(
  216.     "graphics", &GraphicsInitialize, &GraphicsConstruct
  217.     );
  218.     Picture* pict = (Picture*) (*(*TheManager->GetRoot())[1])();
  219.     pict->SetTransformer(nil);
  220.     return pict;
  221. }
  222.  
  223. /* Implementation of View class **********************************************/
  224.  
  225. View::View (Graphic* g) : (nil, g) {
  226.     input = new Sensor(updownEvents);
  227.     input->Catch(KeyEvent);
  228.     damage = nil;
  229. }
  230.  
  231. View::~View () { delete damage; }
  232.  
  233. void View::Handle (Event& e) {
  234.     Coord slop = round(cm/15);
  235.     Picture* pict = (Picture*) graphic;
  236.     Graphic* g;
  237.  
  238.     if (e.eventType == DownEvent) {
  239.     BoxObj b = BoxObj(e.x-slop, e.y-slop, e.x+slop, e.y+slop);
  240.     g = pict->LastGraphicIntersecting(b);
  241.     if (g != nil) {
  242.         switch (e.button) {
  243.         case LEFTMOUSE:
  244.         Move(g, e); break;
  245.         case MIDDLEMOUSE: 
  246.         Scale(g, e); break;
  247.         case RIGHTMOUSE:
  248.         Rotate(g, e); break;
  249.         }
  250.     }
  251.     } else if (e.eventType == KeyEvent && *e.keystring == 'q') {
  252.     e.target = nil;
  253.     }    
  254. }
  255.  
  256. void View::Move (Graphic* g, Event& e) {
  257.     Coord l, b, r, t, newl, newb;
  258.     float dx, dy, mag = GetMagnification();
  259.     
  260.     damage->Incur(g);
  261.     g->GetBox(l, b, r, t);
  262.     SlidingRect sr(output, canvas, l, b, r, t, e.x, e.y);
  263.  
  264.     Track(e, sr);
  265.     sr.GetCurrent(newl, newb, r, t);
  266.     dx = (newl - l) / mag;  // get distance moved, corrected to reflect
  267.     dy = (newb - b) / mag;  // current magnification
  268.     g->Translate(dx, dy);
  269.     g->Touch();             // so that new position will be written out
  270.     damage->Incur(g);
  271.     Update();
  272. }
  273.  
  274. void View::Scale (Graphic* g, Event& e) {
  275.     Coord l, b, r, t;
  276.     float cx, cy, scale;
  277.     
  278.     damage->Incur(g);
  279.     g->GetBox(l, b, r, t);
  280.     g->GetCenter(cx, cy);
  281.     ScalingRect sr(output, canvas, l, b, r, t, round(cx), round(cy));
  282.  
  283.     Track(e, sr);
  284.     scale = sr.CurrentScaling();
  285.     g->Scale(scale, scale, cx, cy);
  286.     g->Touch();
  287.     damage->Incur(g);
  288.     Update();
  289. }
  290.  
  291. void View::Rotate (Graphic* g, Event& e) {
  292.     Coord l, b, r, t;
  293.     float cx, cy;
  294.     
  295.     damage->Incur(g);
  296.     g->GetBox(l, b, r, t);
  297.     g->GetCenter(cx, cy);
  298.     RotatingRect rr(output, canvas, l, b, r, t, round(cx), round(cy), e.x,e.y);
  299.  
  300.     Track(e, rr);
  301.     g->Rotate(rr.CurrentAngle(), cx, cy);
  302.     g->Touch();
  303.     damage->Incur(g);
  304.     Update();
  305. }
  306.  
  307. void View::Update () {
  308.     UpdatePerspective();
  309.     damage->Repair();
  310. }
  311.  
  312. void View::Draw () {
  313.     damage->Reset();
  314.     GraphicBlock::Draw();
  315. }
  316.  
  317. void View::Resize () {
  318.     GraphicBlock::Resize();
  319.     if (damage == nil) {
  320.     damage = new Damage(canvas, output, GetGraphic());
  321.     }
  322. }
  323.  
  324. void View::Track (Event& e, Rubberband& r) {
  325.     r.Draw();
  326.  
  327.     Listen(allEvents);
  328.     do {
  329.     if (e.eventType == MotionEvent) {
  330.         r.Track(e.x, e.y);
  331.     }
  332.     Read(e);
  333.     } while (e.eventType != UpEvent);
  334.     Listen(input);
  335.  
  336.     r.Erase();
  337. }
  338.  
  339. /* Main program **************************************************************/
  340.  
  341. int IVMain (int argc, char** argv) {
  342.     register int i;
  343.     boolean save = false;
  344.  
  345.     World* world = new World("graphics", argc, argv);
  346.  
  347.     for (i = 1; i < argc; i++) {
  348.     if (strcmp(argv[i], "-s") == 0) {
  349.         save = true;
  350.     } else {
  351.         fprintf(stderr, "bad arg %s\n", argv[i]);
  352.         exit(1);
  353.     }
  354.     }
  355.  
  356.     Graphics* graphics = new Graphics;
  357.     world->InsertApplication(graphics);
  358.     graphics->Run();
  359.     delete graphics;
  360.     if (save) {
  361.     delete TheManager;
  362.     }
  363.     return 0;
  364. }
  365.