/* * 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. */ /* * Box - tiling glyph */ #include #include #include #include #include #include #include #include #include #include class BoxImpl { private: friend class Box; Box* box_; Layout* layout_; boolean requested_; Requisition requisition_; AllocationTable* allocations_; static Extension* empty_ext_; void request(); AllocationInfo& info(Canvas*, const Allocation&, Extension&); void offset_allocate(AllocationInfo&, Coord dx, Coord dy); void full_allocate(AllocationInfo&); void invalidate(); }; Extension* BoxImpl::empty_ext_; Box::Box(Layout* layout, GlyphIndex size) : PolyGlyph(size) { BoxImpl* b = new BoxImpl; impl_ = b; b->box_ = this; b->layout_ = layout; b->requested_ = false; b->allocations_ = nil; } Box::Box( Layout* layout, Glyph* g1, Glyph* g2, Glyph* g3, Glyph* g4, Glyph* g5, Glyph* g6, Glyph* g7, Glyph* g8, Glyph* g9, Glyph* g10 ) : PolyGlyph(4) { BoxImpl* b = new BoxImpl; impl_ = b; b->box_ = this; b->layout_ = layout; b->requested_ = false; b->allocations_ = nil; if (g1 != nil) { append(g1); } if (g2 != nil) { append(g2); } if (g3 != nil) { append(g3); } if (g4 != nil) { append(g4); } if (g5 != nil) { append(g5); } if (g6 != nil) { append(g6); } if (g7 != nil) { append(g7); } if (g8 != nil) { append(g8); } if (g9 != nil) { append(g9); } if (g10 != nil) { append(g10); } } Box::~Box() { BoxImpl* b = impl_; delete b->layout_; delete b->allocations_; delete b; } void Box::request(Requisition& requisition) const { BoxImpl* b = impl_; if (!b->requested_) { b->request(); } requisition = b->requisition_; } void Box::allocate(Canvas* c, const Allocation& allocation, Extension& ext) { impl_->info(c, allocation, ext); } void Box::draw(Canvas* c, const Allocation& allocation) const { BoxImpl* b = impl_; Extension ext; ext.clear(); AllocationInfo& info = b->info(c, allocation, ext); if (c->damaged(ext)) { Allocation* a = info.component_allocations(); GlyphIndex n = count(); for (GlyphIndex i = 0; i < n; i++) { Glyph* g = component(i); if (g != nil) { g->draw(c, a[i]); } } } } void Box::print(Printer* p, const Allocation& allocation) const { BoxImpl* b = impl_; Extension ext; ext.clear(); AllocationInfo& info = b->info(p, allocation, ext); if (p->damaged(ext)) { Allocation* a = info.component_allocations(); GlyphIndex n = count(); for (GlyphIndex i = 0; i < n; i++) { Glyph* g = component(i); if (g != nil) { g->print(p, a[i]); } } } } void Box::pick(Canvas* c, const Allocation& a, int depth, Hit& h) { if (h.right() >= a.left() && h.left() < a.right() && h.top() >= a.bottom() && h.bottom() < a.top() ) { BoxImpl* b = impl_; Extension ext; ext.clear(); AllocationInfo& info = b->info(c, a, ext); Allocation* aa = info.component_allocations(); GlyphIndex n = count(); for (GlyphIndex i = 0; i < n; i++) { Glyph* g = component(i); if (g != nil) { h.begin(depth, this, i); g->pick(c, aa[i], depth + 1, h); h.end(); } } } } void Box::undraw() { AllocationTable* table = impl_->allocations_; if (table != nil) { table->flush(); } PolyGlyph::undraw(); } void Box::modified(GlyphIndex) { impl_->invalidate(); } void Box::allotment(GlyphIndex index, DimensionName d, Allotment& a) const { AllocationTable* table = impl_->allocations_; if (table != nil) { AllocationInfo* info = table->most_recent(); if (info != nil) { Allocation* allocations = info->component_allocations(); a = allocations[index].allotment(d); } } } /* class BoxImpl */ void BoxImpl::request() { GlyphIndex count = box_->count(); Requisition* r = new Requisition[count]; for (GlyphIndex i = 0; i < count; i++) { Glyph* g = box_->component(i); if (g != nil) { g->request(r[i]); } } layout_->request(count, r, requisition_); requested_ = true; delete [] r; } AllocationInfo& BoxImpl::info(Canvas* c, const Allocation& a, Extension& ext) { if (allocations_ == nil) { allocations_ = new AllocationTable(box_->count()); } AllocationInfo* info = allocations_->find(c, a); if (info == nil) { Coord dx, dy; info = allocations_->find_same_size(c, a, dx, dy); if (info != nil) { info->extension(ext); offset_allocate(*info, dx, dy); } else { info = allocations_->allocate(c, a); info->extension(ext); full_allocate(*info); } } ext = info->extension(); return *info; } void BoxImpl::offset_allocate(AllocationInfo& info, Coord dx, Coord dy) { Canvas* c = info.canvas(); Allocation* a = info.component_allocations(); Extension& box = info.extension(); Extension child; GlyphIndex n = box_->count(); for (GlyphIndex i = 0; i < n; i++) { Glyph* g = box_->component(i); if (g != nil) { Allocation& a_i = a[i]; Allotment& ax = a_i.x_allotment(); Allotment& ay = a_i.y_allotment(); ax.offset(dx); ay.offset(dy); child.clear(); g->allocate(c, a_i, child); box.merge(child); } } } void BoxImpl::full_allocate(AllocationInfo& info) { Canvas* c = info.canvas(); GlyphIndex n = box_->count(); Allocation* a = info.component_allocations(); Requisition* r = new Requisition[n]; GlyphIndex i; for (i = 0; i < n; i++) { Glyph* g = box_->component(i); if (g != nil) { g->request(r[i]); } } layout_->allocate(info.allocation(), n, r, a); delete [] r; Extension& box = info.extension(); Extension child; for (i = 0; i < n; i++) { Glyph* g = box_->component(i); if (g != nil) { child.clear(); g->allocate(c, a[i], child); box.merge(child); } } } void BoxImpl::invalidate() { requested_ = false; delete allocations_; allocations_ = nil; }