From: daw@sc.zuken.com (Don Walters)
Subject: Re: rubberbanding
Organization: Internet-USENET Gateway at Stanford University
Date: Wed, 22 Jul 1992 16:30:40 GMT

Thanks for the example on how to rubberband.  It certainly looks
easy enough, but I am clearly not understanding something yet
(and starting to feel pretty dense :-).  I tried using your
approach in my code, and got different results, so I went back
to your example and replaced the "TransformFitter(new Image" line
with a line to instance my own Glyph which draws some graphics.
I must not be doing something properly in my Glyph, because now when
I do the "press/drag/release" the image clears, the rubberband
box seems to draw on top of itself (so you get a sort of upside-down
L shape) and when your release, the rubberband box is left behind.

The code is below.  Please tell me what I need to do differently.
I have commented the lines I changed...

Thanks,

Don Walters
daw@zuken.com

#include <IV-look/kit.h>
//******** ADDED FOLLOWING INCLUDE
#include <InterViews/background.h>
#include <InterViews/brush.h>
#include <InterViews/color.h>
#include <InterViews/display.h>
#include <InterViews/event.h>
#include <InterViews/image.h>
#include <InterViews/input.h>
#include <InterViews/layout.h>
#include <InterViews/raster.h>
#include <InterViews/tiff.h>
#include <InterViews/session.h>
#include <InterViews/style.h>
#include <InterViews/transformer.h>
#include <InterViews/tformsetter.h>
#include <InterViews/window.h>
#include <stdio.h>
#include <stdlib.h>

//******** ADDED THIS GLYPH DEFINITION
//
// Class which defines glyph to contain graphics.
//
class DrawGlyph : public Glyph {
public:
        DrawGlyph();
        virtual ~DrawGlyph();

        virtual void allocate(Canvas*, const Allocation&, Extension&);
        virtual void request(Requisition&) const;
        virtual void draw(Canvas*, const Allocation&) const;

private:
        Requirement* rx;
        Requirement* ry;
	Brush* brush_;
	Color* color_;
};

DrawGlyph::DrawGlyph()
  {
        rx = new Requirement(150, 0, 0, 0);
        ry = new Requirement(150, 0, 0, 0);
	brush_ = new Brush(0);
	Resource::ref(brush_);
	color_ = new Color(*WidgetKit::instance()->foreground());
	Resource::ref(color_);
  }

DrawGlyph::~DrawGlyph()
  {
	Resource::unref(brush_);
	Resource::unref(color_);
  }

void DrawGlyph::request(Requisition& req) const
  {
        req.require(Dimension_X, *rx);
        req.require(Dimension_Y, *ry);
  }

void DrawGlyph::allocate(Canvas* c, const Allocation& a, Extension& ext)
  {
        ext.set(c, a);
  }

void DrawGlyph::draw(Canvas* c, const Allocation&) const
  {
	//
	// Here I draw my own graphics...
	//
	c->rect(20, 20, 100, 100, color_, brush_);
	c->rect(30, 30, 110, 110, color_, brush_);
  }
//******** END OF NEW CODE

class Selector : public InputHandler {
public:
    Selector(Glyph*, Style*);
    virtual ~Selector();

    virtual void draw(Canvas*, const Allocation&) const;

    virtual void press(const Event&);
    virtual void drag(const Event&);
    virtual void release(const Event&);
private:
    Brush* brush_;
    Color* color_;
    Coord x0_;
    Coord y0_;
    Coord x1_;
    Coord y1_;
    Coord x2_;
    Coord y2_;
    boolean drawn_;
    boolean overlay_damage_;
    boolean overlay_done_;
};

Selector::Selector(Glyph* g, Style* s) : InputHandler(g, s) {
    brush_ = new Brush(0);
    Resource::ref(brush_);
    color_ = new Color(*WidgetKit::instance()->background(), 1.0, Color::Xor);
    Resource::ref(color_);
    drawn_ = false;
    overlay_damage_ = false;
    overlay_done_ = false;
}

Selector::~Selector() {
    Resource::unref(brush_);
    Resource::unref(color_);
}

void Selector::draw(Canvas* c, const Allocation& a) const {
    if (overlay_damage_) {
	Transformer identity;
	c->push_transform();
	c->transformer(identity);
	if (drawn_) {
	    c->rect(x0_, y0_, x1_, y1_, color_, brush_);
	}
	Selector* s = (Selector*)this;
	if (overlay_done_) {
	    s->drawn_ = false;
	    s->overlay_damage_ = false;
	    s->overlay_done_ = false;
	} else {
	    c->rect(x0_, y0_, x2_, y2_, color_, brush_);
	    s->x1_ = s->x2_;
	    s->y1_ = s->y2_;
	    s->drawn_ = true;
	}
	c->pop_transform();
    } else {
	InputHandler::draw(c, a);
    }
}

void Selector::press(const Event& e) {
    x0_ = e.pointer_x();
    y0_ = e.pointer_y();
    InputHandler::press(e);
}

void Selector::drag(const Event& e) {
    x2_ = e.pointer_x();
    y2_ = e.pointer_y();
    overlay_damage_ = true;
    redraw();
}

void Selector::release(const Event& e) {
    overlay_damage_ = true;
    overlay_done_ = true;
    redraw();
    InputHandler::release(e);
}

static PropertyData props[] = {
//  { "*visual", "TrueColor" },
    { nil }
};

static OptionDesc options[] = {
    { nil }
};

int main(int argc, char** argv) {
    Session* session = new Session("Ipaste", argc, argv, options, props);

/******** Commented out loading of TIFF FILE
    if (argc == 1) {
	fprintf(stderr, "Usage: %s <file>\n", argv[0]);
	exit(1);
    }

    Raster* rast = TIFFRaster::load(argv[1]);
    if (rast == nil) {
	fprintf(stderr, "%s: open tiff image %s failed\n", argv[0], argv[1]);
	exit(1);
    }
********/

    Style* style = session->default_display()->style();
    const LayoutKit& layout = *LayoutKit::instance();
    session->run_window(
	new ApplicationWindow(
//******** INSERT IN BACKGROUND
	    new Background(
	        layout.flexible(
		    new Selector(
//******** LOAD MY OWN GLYPH
		        new DrawGlyph(), style
//		        new TransformFitter(new Image(rast)), style
		    )
	        ),
		WidgetKit::instance()->background()
	    )
	)
    );
}

Newsgroups: comp.windows.interviews