/* * Copyright (c) 1987, 1988, 1989, 1990, 1991 Stanford University * Copyright (c) 1991 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Stanford and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Stanford and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL STANFORD OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * Page - arbitrary placements */ #include #include #include #include #include static const int PageInfoAllocated = 0x01; static const int PageInfoExtended = 0x02; // static const int PageInfoPositioned = 0x04; static const int PageInfoHidden = 0x08; class PageInfo { public: PageInfo(); Glyph* glyph_; Allocation allocation_; Extension extension_; Coord x_; Coord y_; int status_; }; PageInfo::PageInfo() { glyph_ = nil; x_ = 0; y_ = 0; status_ = 0; } declareList(PageInfo_List,PageInfo) implementList(PageInfo_List,PageInfo) static const float epsilon = 0.1; Page::Page(Glyph* bg) : Glyph() { Resource::ref(bg); background_ = bg; canvas_ = nil; info_ = new PageInfo_List(); } Page::~Page() { GlyphIndex count = info_->count(); for (GlyphIndex i = 0; i < count; ++i) { PageInfo& info = info_->item_ref(i); Resource::unref(info.glyph_); } delete info_; info_ = nil; Resource::unref(background_); canvas_ = nil; } Coord Page::left() const { return allocation_.left(); } Coord Page::right() const { return allocation_.right(); } Coord Page::bottom() const { return allocation_.bottom(); } Coord Page::top() const { return allocation_.top(); } Coord Page::x() const { return allocation_.x(); } Coord Page::y() const { return allocation_.y(); } void Page::show(GlyphIndex index, boolean showing) { PageInfo& info = info_->item_ref(index); if (((info.status_ & PageInfoHidden) == 0) != showing) { if (canvas_ != nil) { canvas_->damage(info.extension_); } if (showing) { info.status_ &= ~PageInfoHidden; } else { info.status_ |= PageInfoHidden; } } } boolean Page::showing(GlyphIndex index) const { return (info_->item_ref(index).status_ & PageInfoHidden) == 0; } void Page::move(GlyphIndex index, Coord x, Coord y) { PageInfo& info = info_->item_ref(index); if ( (info.status_ & PageInfoAllocated) && (info.x_ != x || info.y_ != y) ) { Extension& b = info.extension_; Allocation& a = info.allocation_; Allotment& ax = a.allotment(Dimension_X); Allotment& ay = a.allotment(Dimension_Y); Coord newx = allocation_.x() + x; Coord newy = allocation_.y() + y; Allotment n_ax(newx, ax.span(), ax.alignment()); Allotment n_ay(newy, ay.span(), ay.alignment()); a.allot(Dimension_X, n_ax); a.allot(Dimension_Y, n_ay); if (canvas_ != nil) { canvas_->damage(b); } b.clear(); info.glyph_->allocate(canvas_, a, b); if (canvas_ != nil) { canvas_->damage(b); } } info.x_ = x; info.y_ = y; } void Page::location(GlyphIndex index, Coord& x, Coord& y) { PageInfo& info = info_->item_ref(index); x = info.x_; y = info.y_; } GlyphIndex Page::count() const { return info_->count(); } Glyph* Page::component(GlyphIndex index) const { return info_->item_ref(index).glyph_; } void Page::allotment(GlyphIndex index, DimensionName res, Allotment& a) const { a = info_->item_ref(index).allocation_.allotment(res); } void Page::change(GlyphIndex index) { PageInfo& info = info_->item_ref(index); info.status_ &= ~(PageInfoAllocated); } void Page::append(Glyph* glyph) { PageInfo info; info.glyph_ = glyph; info.status_ = 0; info.x_ = 0; info.y_ = 0; info_->append(info); Resource::ref(glyph); } void Page::prepend(Glyph* glyph) { PageInfo info; info.glyph_ = glyph; info.status_ = 0; info.x_ = 0; info.y_ = 0; info_->prepend(info); Resource::ref(glyph); } void Page::insert(GlyphIndex index, Glyph* glyph) { PageInfo info; info.glyph_ = glyph; info.status_ = 0; info.x_ = 0; info.y_ = 0; info_->insert(index, info); Resource::ref(glyph); } void Page::remove(GlyphIndex index) { PageInfo& info = info_->item_ref(index); if (canvas_ != nil && (info.status_ & PageInfoAllocated)) { canvas_->damage(info.extension_); } Resource::unref(info.glyph_); info_->remove(index); } void Page::replace(GlyphIndex index, Glyph* glyph) { PageInfo& info = info_->item_ref(index); if (canvas_ != nil && (info.status_ & PageInfoAllocated)) { canvas_->damage(info.extension_); } Resource::ref(glyph); Resource::unref(info.glyph_); info.glyph_ = glyph; info.status_ &= ~(PageInfoAllocated); } void Page::request(Requisition& requisition) const { if (background_ != nil) { background_->request(requisition); } } void Page::allocate(Canvas* c, const Allocation& allocation, Extension& ext) { canvas_ = c; allocation_ = allocation; if (background_ != nil) { background_->allocate(c, allocation, ext); } GlyphIndex count = info_->count(); for (GlyphIndex index = 0; index < count; ++index) { PageInfo& info = info_->item_ref(index); if (info.glyph_ != nil) { Allocation& a = info.allocation_; Extension& b = info.extension_; Requisition s; info.glyph_->request(s); Allotment ax = Allotment( allocation.x() + info.x_, s.requirement(Dimension_X).natural(), s.requirement(Dimension_X).alignment() ); Allotment ay = Allotment( allocation.y() + info.y_, s.requirement(Dimension_Y).natural(), s.requirement(Dimension_Y).alignment() ); if ( !(info.status_ & PageInfoAllocated) || !ax.equals(a.allotment(Dimension_X), epsilon) || !ay.equals(a.allotment(Dimension_Y), epsilon) ) { if (c != nil && (info.status_ & PageInfoExtended)) { c->damage(b); } a.allot(Dimension_X, ax); a.allot(Dimension_Y, ay); b.clear(); info.glyph_->allocate(c, a, b); if (c != nil) { c->damage(b); } } info.status_ |= PageInfoAllocated|PageInfoExtended; ext.merge(b); } } } void Page::draw(Canvas* canvas, const Allocation& a) const { if (background_ != nil) { background_->draw(canvas, a); } GlyphIndex count = info_->count(); for (GlyphIndex index = 0; index < count; ++index) { PageInfo& info = info_->item_ref(index); if (info.glyph_ != nil && !(info.status_ & PageInfoHidden)) { Allocation& a = info.allocation_; Extension& b = info.extension_; if (canvas->damaged(b)) { info.glyph_->draw(canvas, a); } } } } void Page::print(Printer* p, const Allocation& a) const { if (background_ != nil) { background_->print(p, a); } GlyphIndex count = info_->count(); for (GlyphIndex index = 0; index < count; ++index) { PageInfo& info = info_->item_ref(index); if (info.glyph_ != nil && !(info.status_ & PageInfoHidden)) { Allocation& a = info.allocation_; Extension& b = info.extension_; if (p->damaged(b)) { info.glyph_->print(p, a); } } } } void Page::undraw() { if (background_ != nil) { background_->undraw(); } GlyphIndex count = info_->count(); for (GlyphIndex i = 0; i < count; i++) { const PageInfo& info = info_->item_ref(i); Glyph* g = info.glyph_; if (g != nil) { g->undraw(); } } canvas_ = nil; } void Page::pick(Canvas* c, const Allocation& a, int depth, Hit& h) { if (background_ != nil) { background_->pick(c, a, depth, h); } GlyphIndex count = info_->count(); for (GlyphIndex index = 0; index < count; ++index) { PageInfo& info = info_->item_ref(index); if (info.glyph_ != nil && !(info.status_ & PageInfoHidden)) { Allocation& a = info.allocation_; if (h.right() >= a.left() && h.left() < a.right() && h.top() >= a.bottom() && h.bottom() < a.top() ) { h.begin(depth, this, index); info.glyph_->pick(c, a, depth + 1, h); h.end(); } } } }