/* * Copyright (c) 1990, 1991 Stanford University * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided * that the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Stanford not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. Stanford makes no representations about * the suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * STANFORD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * Implementation of StateVarView subclasses. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*****************************************************************************/ static const int VIEW_WIDTH = 30; static const int VIEW_HEIGHT = 15; static const int HPAD = 2; static const int VPAD = 2; static const char* GRAVITY_ON = "gravity on"; static const char* MODIFIED = "*"; static const char* WPROTECTED = "%"; static const char* UNMODIFIED = " "; static const char* NONE = "None"; static const char* UNNAMED = "[unnamed]"; /*****************************************************************************/ class TextInteractor : public Interactor { public: TextInteractor(const char*, Alignment = Center); virtual ~TextInteractor(); void SetText(const char*); const char* GetText(); protected: void Align(); virtual void Reconfig(); virtual void Redraw(Coord, Coord, Coord, Coord); protected: char* _text; Alignment _alignment; }; TextInteractor::TextInteractor (const char* t, Alignment a) { _text = strdup(t); _alignment = a; } TextInteractor::~TextInteractor () { delete _text; } void TextInteractor::SetText (const char* t) { free(_text); _text = strdup(t); } const char* TextInteractor::GetText () { return _text; } void TextInteractor::Align () { const Font* f = output->GetFont(); int width = f->Width(_text); int height = f->Height(); Coord x; switch (_alignment) { case Left: x = HPAD; break; case Center: x = (xmax - width + 1)/2; break; case Right: x = xmax - width - HPAD; break; } output->MoveTo(x, (ymax - height+ 1)/2); } void TextInteractor::Reconfig () { const Font* f = output->GetFont(); int width = f->Width(_text); shape->Rect(width + 2*HPAD, f->Height() + 2*VPAD); shape->Rigid(width, hfil, 0, 0); } void TextInteractor::Redraw (Coord, Coord, Coord, Coord) { if (canvas != nil) { Align(); output->ClearRect(canvas, 0, 0, xmax, ymax); output->Text(canvas, _text); } } /*****************************************************************************/ NameVarView::NameVarView ( NameVar* n, Alignment a, const char* samp ) : StateVarView(n) { const char* sample = (samp == nil) ? "nnnnnnnnnnnnnnnnnnnnnn" : samp; TextInteractor* t = new TextInteractor(sample, a); Insert(t); } boolean NameVarView::Stale () { const char* name = ((NameVar*) _subject)->GetName(); const char* text = ((TextInteractor*) interior())->GetText(); return (name == nil && strcmp(text, UNNAMED) != 0) || (name != nil && strcmp(text, name) != 0); } void NameVarView::Init() { const char* name = ((NameVar*) _subject)->GetName(); TextInteractor* t = (TextInteractor*) interior(); if (name == nil) { t->SetText(UNNAMED); } else { t->SetText(name); } } /*****************************************************************************/ FileNameVarView::FileNameVarView ( NameVar* n, Alignment a, boolean relative, const char* samp ) : StateVarView(n) { const char* sample = (samp == nil) ? "nnnnnnnnnnnnnnnnnnnnnn" : samp; TextInteractor* t = new TextInteractor(sample, a); _relative = relative; Insert(t); } void FileNameVarView::Init() { const char* name = ((NameVar*) _subject)->GetName(); TextInteractor* t = (TextInteractor*) interior(); if (name == nil) { t->SetText(UNNAMED); } else if (_relative) { const char* relname = strrchr(name, '/'); if (relname == nil) { t->SetText(name); } else { t->SetText(++relname); } } else { t->SetText(name); } } /*****************************************************************************/ CompNameVarView::CompNameVarView ( CompNameVar* n, Alignment a, boolean relative, const char* samp ) : StateVarView(n) { const char* sample = (samp == nil) ? "nnnnnnnnnnnnnnnnnnn" : samp; TextInteractor* t = new TextInteractor(sample, a); _relative = relative; Insert(t); } void CompNameVarView::Init() { CompNameVar* subj = (CompNameVar*) _subject; const char* name = subj->GetName(); TextInteractor* t = (TextInteractor*) interior(); if (name == nil) { t->SetText(UNNAMED); } else { char buf[CHARBUFSIZE]; buf[0] = '\0'; if (subj->PartOf() != nil) { strcat(buf, "[part of] "); } if (_relative) { const char* relname = strrchr(name, '/'); if (relname == nil) { strcat(buf, name); } else { strcat(buf, ++relname); } } else { strcat(buf, name); } t->SetText(buf); } } /*****************************************************************************/ ModifStatusVarView::ModifStatusVarView ( ModifStatusVar* m, Alignment a ) : StateVarView(m) { TextInteractor* t = new TextInteractor(" ", a); Insert(t); } boolean ModifStatusVarView::Stale () { ModifStatusVar* msv = (ModifStatusVar*) _subject; return msv->GetModifStatus() != _prevVal || WriteProtected() != _prevProt; } boolean ModifStatusVarView::WriteProtected () { ModifStatusVar* msv = (ModifStatusVar*) _subject; Catalog* catalog = unidraw->GetCatalog(); const char* name = catalog->GetName(msv->GetComponent()); return name != nil && catalog->Exists(name) && !catalog->Writable(name); } void ModifStatusVarView::Init () { ModifStatusVar* msv = (ModifStatusVar*) _subject; TextInteractor* t = (TextInteractor*) interior(); _prevVal = msv->GetModifStatus(); _prevProt = WriteProtected(); if (_prevProt) { t->SetText(WPROTECTED); } else if (_prevVal) { t->SetText(MODIFIED); } else { t->SetText(UNMODIFIED); } } void ModifStatusVarView::Reconfig () { StateVarView::Reconfig(); shape->Rigid(); } /*****************************************************************************/ MagnifVarView::MagnifVarView (MagnifVar* m, Alignment a) : StateVarView(m) { TextInteractor* t = new TextInteractor("nnnnnnnnnn", a); Insert(t); } boolean MagnifVarView::Stale () { return ((MagnifVar*) _subject)->GetMagnif() != _prevVal; } void MagnifVarView::Init() { float mag = ((MagnifVar*) _subject)->GetMagnif(); TextInteractor* t = (TextInteractor*) interior(); char buf[32]; _prevVal = mag; sprintf(buf, "mag %gx", mag); t->SetText(buf); } /*****************************************************************************/ GravityVarView::GravityVarView (GravityVar* m, Alignment a) : StateVarView(m) { TextInteractor* t = new TextInteractor(GRAVITY_ON, a); Insert(t); } boolean GravityVarView::Stale () { return ((GravityVar*) _subject)->IsActive() != _prevVal; } void GravityVarView::Init() { boolean active = ((GravityVar*) _subject)->IsActive(); TextInteractor* t = (TextInteractor*) interior(); const char* string = active ? GRAVITY_ON : ""; _prevVal = active; t->SetText(string); } /*****************************************************************************/ FontVarView::FontVarView ( FontVar* f, Alignment a, const char* samp ) : StateVarView(f) { const char* sample = (samp == nil) ? "nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn" : samp; TextInteractor* t = new TextInteractor(sample, a); Insert(t); } boolean FontVarView::Stale () { return ((FontVar*) _subject)->GetFont() != _prevVal; } void FontVarView::Init () { PSFont* f = ((FontVar*) _subject)->GetFont(); const char* name = f->GetPrintFontAndSize(); TextInteractor* t = (TextInteractor*) interior(); _prevVal = f; t->SetText(name); } /*****************************************************************************/ static void CenterText ( const char* text, Painter* output, Coord xmax, Coord ymax ) { const Font* f = output->GetFont(); int width = f->Width(text); int height = f->Height(); output->MoveTo((xmax - width + 1)/2, (ymax - height + 1)/2); } /*****************************************************************************/ class BrushInteractor : public Interactor { public: BrushInteractor(PSBrush*, PSColor* fg = nil, PSColor* bg = nil); virtual ~BrushInteractor(); void SetBrush(PSBrush*); void SetColors(PSColor*, PSColor*); PSBrush* GetBrush(); PSColor* GetFgColor(); PSColor* GetBgColor(); protected: virtual void Reconfig(); virtual void Redraw(Coord, Coord, Coord, Coord); protected: PSBrush* _brush; PSColor* _fg, *_bg; }; BrushInteractor::BrushInteractor (PSBrush* b, PSColor* fg, PSColor* bg) { _brush = b; _fg = fg; _bg = bg; Ref(_brush); Ref(_fg); Ref(_bg); } BrushInteractor::~BrushInteractor () { Unref(_brush); Unref(_fg); Unref(_bg); } void BrushInteractor::SetBrush (PSBrush* b) { Ref(b); Unref(_brush); _brush = b; } PSBrush* BrushInteractor::GetBrush () { return _brush; } void BrushInteractor::SetColors (PSColor* fg, PSColor* bg) { Ref(fg); Ref(bg); Unref(_fg); Unref(_bg); _fg = fg; _bg = bg; } PSColor* BrushInteractor::GetFgColor () { return _fg; } PSColor* BrushInteractor::GetBgColor () { return _bg; } void BrushInteractor::Reconfig () { Painter* tmp = output; output = new Painter(tmp); Ref(output); Unref(tmp); const Font* f = output->GetFont(); shape->width = max(f->Width(NONE) + 2*HPAD, VIEW_WIDTH); shape->height = max(f->Height() + 2*VPAD, VIEW_HEIGHT); shape->Rigid(shape->width/2, shape->width, shape->height/2, shape->height); } void BrushInteractor::Redraw (Coord, Coord, Coord, Coord) { if (canvas != nil) { output->ClearRect(canvas, 0, 0, xmax, ymax); if (_brush->None()) { CenterText(NONE, output, xmax, ymax); output->Text(canvas, NONE); } else { const Color* origfg = output->GetFgColor(); const Color* origbg = output->GetBgColor(); Resource::ref(origfg); Resource::ref(origbg); output->SetBrush(_brush); output->SetColors(_fg, _bg); #if __GNUC__>=2 && __GNUC_MINOR__>=5 || __GNUC__>=3 #undef Line output->Line(canvas, HPAD, ymax/2, xmax-HPAD, ymax/2); #define Line _lib_iv(Line) #else output->Line(canvas, HPAD, ymax/2, xmax-HPAD, ymax/2); #endif /* Line */ if (_brush->Width() == 0) { CenterText("0", output, xmax, ymax); output->Text(canvas, "0"); } output->SetColors(origfg, origbg); Resource::unref(origfg); Resource::unref(origbg); } } } /*****************************************************************************/ BrushVarView::BrushVarView (BrushVar* bv, ColorVar* cv) : StateVarView(bv) { PSColor* fg = nil, *bg = nil; _colorSubj = cv; if (_colorSubj != nil) { _colorSubj->Attach(this); _subject = bv; // Attach changes _subject fg = _colorSubj->GetFgColor(); bg = _colorSubj->GetBgColor(); } BrushInteractor* b = new BrushInteractor(bv->GetBrush(), fg, bg); Insert(b); } BrushVarView::~BrushVarView () { if (_colorSubj != nil) { StateVar* subject = _subject; // Detach changes _subject _colorSubj->Detach(this); _subject = subject; } } boolean BrushVarView::Stale () { boolean colorsChanged = ( (_colorSubj != nil) && ( _colorSubj->GetFgColor() != _prevFg || _colorSubj->GetBgColor() != _prevBg ) ); return ((BrushVar*) _subject)->GetBrush() != _prevVal || colorsChanged; } void BrushVarView::Init () { BrushInteractor* b = (BrushInteractor*) interior(); _prevVal = ((BrushVar*) _subject)->GetBrush(); b->SetBrush(_prevVal); if (_colorSubj != nil) { _prevFg = _colorSubj->GetFgColor(); _prevBg = _colorSubj->GetBgColor(); b->SetColors(_prevFg, _prevBg); } } /*****************************************************************************/ class PatternInteractor : public Interactor { public: PatternInteractor(PSPattern*, PSColor* fg = nil, PSColor* bg = nil); virtual ~PatternInteractor(); void SetPattern(PSPattern*); void SetColors(PSColor*, PSColor*); PSPattern* GetPattern(); PSColor* GetFgColor(); PSColor* GetBgColor(); protected: virtual void Reconfig(); virtual void Redraw(Coord, Coord, Coord, Coord); protected: PSPattern* _pattern; PSColor* _fg, *_bg; }; PatternInteractor::PatternInteractor (PSPattern* p, PSColor* fg, PSColor* bg) { _pattern = p; _fg = fg; _bg = bg; Ref(_pattern); Ref(_fg); Ref(_bg); } PatternInteractor::~PatternInteractor () { Unref(_pattern); Unref(_fg); Unref(_bg); } void PatternInteractor::SetPattern (PSPattern* p) { Ref(p); Unref(_pattern); _pattern = p; } PSPattern* PatternInteractor::GetPattern () { return _pattern; } void PatternInteractor::SetColors (PSColor* fg, PSColor* bg) { Ref(fg); Ref(bg); Unref(_fg); Unref(_bg); _fg = fg; _bg = bg; } PSColor* PatternInteractor::GetFgColor () { return _fg; } PSColor* PatternInteractor::GetBgColor () { return _bg; } void PatternInteractor::Reconfig () { Painter* tmp = output; output = new Painter(tmp); Ref(output); Unref(tmp); const Font* f = output->GetFont(); shape->width = max(f->Width(NONE) + 2*HPAD, VIEW_WIDTH); shape->height = max(f->Height() + 2*VPAD, VIEW_HEIGHT); shape->Rigid(shape->width/2, shape->width, shape->height/2, shape->height); } void PatternInteractor::Redraw (Coord, Coord, Coord, Coord) { if (canvas != nil) { output->ClearRect(canvas, 0, 0, xmax, ymax); if (_pattern->None()) { CenterText(NONE, output, xmax, ymax); output->Text(canvas, NONE); } else { const Color* origfg = output->GetFgColor(); const Color* origbg = output->GetBgColor(); Resource::ref(origfg); Resource::ref(origbg); output->SetPattern(_pattern); output->SetColors(_fg, _bg); output->FillRect(canvas, HPAD, VPAD, xmax-HPAD, ymax-VPAD); output->Rect(canvas, HPAD, VPAD, xmax-HPAD, ymax-VPAD); output->SetColors(origfg, origbg); Resource::unref(origfg); Resource::unref(origbg); } } } /*****************************************************************************/ PatternVarView::PatternVarView ( PatternVar* pv, ColorVar* cv ) : StateVarView(pv) { PSColor* fg = nil, *bg = nil; _colorSubj = cv; if (_colorSubj != nil) { _colorSubj->Attach(this); _subject = pv; // Attach changes _subject fg = _colorSubj->GetFgColor(); bg = _colorSubj->GetBgColor(); } PatternInteractor* p = new PatternInteractor(pv->GetPattern(), fg, bg); Insert(p); } PatternVarView::~PatternVarView () { if (_colorSubj != nil) { StateVar* subject = _subject; // Detach changes _subject _colorSubj->Detach(this); _subject = subject; } } boolean PatternVarView::Stale () { boolean colorsChanged = ( (_colorSubj != nil) && ( _colorSubj->GetFgColor() != _prevFg || _colorSubj->GetBgColor() != _prevBg ) ); return ((PatternVar*) _subject)->GetPattern() != _prevVal || colorsChanged; } void PatternVarView::Init() { PatternInteractor* p = (PatternInteractor*) interior(); _prevVal = ((PatternVar*) _subject)->GetPattern(); p->SetPattern(_prevVal); if (_colorSubj != nil) { _prevFg = _colorSubj->GetFgColor(); _prevBg = _colorSubj->GetBgColor(); p->SetColors(_prevFg, _prevBg); } }