void CZoominTool::OnMouseMove(_CVIEW* pView, UINT nFlags, CPoint& point) { ::SetCursor(AfxGetApp()->LoadCursor(IDC_ZOOMIN)); CDC* pDC = NULL; pDC = pView->GetDC(); if (pDC == NULL) return; if (!c_bDown) { DeleteDC(pDC->m_hDC); return; } CRect oldRect(c_PtDown,c_PtOld); CRect newRect(c_PtDown,point); //CRect TrackRect; // TrackRect.SetRect(m_StartPoint,point); CPen Pen; if (!Pen.CreatePen(PS_SOLID, 1, RGB(0,0,0))) return; CPen *pOldPen = pDC->SelectObject(&Pen); //int oldDrawMode = m_pDC->SetROP2(R2_XORPEN); int oldDrawMode = pDC->SetROP2(R2_NOT); pDC->SelectStockObject(NULL_BRUSH); pDC->Rectangle(oldRect); pDC->Rectangle(newRect); pDC->SetROP2(oldDrawMode); pDC->SelectObject(pOldPen); Pen.DeleteObject(); DeleteDC(pDC->m_hDC); CDrawTool::OnMouseMove(pView, nFlags, point); }
void AnnotationInterface::UpdateAnnotationRect(bool reset) { // compute current image rectangle for annotation text and leader // also compute its union and rectangle for invalidation (union of old and new rectangles) if (view != 0) { // flag whether leader is to be shown bool showLeader = leaderPlaced && instance.annotationShowLeader; // get view image window ImageWindow w = view->Window(); // store actual rectangles - we'll need them for invalidate rectangle Rect oldRect( totalRect ); // get annotation font pcl::Font f = AnnotationRenderer::GetAnnotationFont( instance ); // compute current text rectangle textRect = Rect( f.Width( instance.annotationText ) + 1, f.Height() + 1 ); textRect.MoveBy( instance.annotationPositionX, instance.annotationPositionY ); // compute leader rectangle if needed if ( showLeader ) { leaderRect = Rect( 11, 11 ); leaderRect.MoveBy( instance.annotationLeaderPositionX - 5, instance.annotationLeaderPositionY - 5 ); } // compute total rectangle (text and leader) using annotation renderer int relPosX, relPosY, dummy3, dummy4; totalRect = AnnotationRenderer::GetBoundingRectangle(instance, relPosX, relPosY, dummy3, dummy4); totalRect.MoveBy(instance.annotationPositionX-relPosX, instance.annotationPositionY-relPosY); // if oldRect is not valid, don't take it into account when computing invalidate rectangle if ( reset ) { invalidateRect = totalRect; } // otherwise make invalidate rectangle union of old and new rectangles else { invalidateRect = totalRect.Union( oldRect ); } } }
bool cgGdiplusRender::PushClipRect( const cgRectF& clipRect ) { Gdiplus::Rect kOregionRect; m_pkGraphics->GetClipBounds(&kOregionRect); cgRectF oldRect(kOregionRect.X, kOregionRect.Y, kOregionRect.Width, kOregionRect.Height); cgRectF finalRect; if (cgXGetIntersectRect(oldRect, clipRect, finalRect)) { Gdiplus::Rect kNewRect(finalRect.x, finalRect.y, finalRect.w, finalRect.h); m_pkGraphics->SetClip(kNewRect); m_kClipRectStack.push(kOregionRect); return true; } return false; }
NS_IMETHODIMP nsStackLayout::Layout(nsIBox* aBox, nsBoxLayoutState& aState) { nsRect clientRect; aBox->GetClientRect(clientRect); PRBool grow; do { nsIBox* child = aBox->GetChildBox(); grow = PR_FALSE; while (child) { nsMargin margin; child->GetMargin(margin); nsRect childRect(clientRect); childRect.Deflate(margin); if (childRect.width < 0) childRect.width = 0; if (childRect.height < 0) childRect.height = 0; nsRect oldRect(child->GetRect()); PRBool sizeChanged = (oldRect != childRect); // only lay out dirty children or children whose sizes have changed if (sizeChanged || NS_SUBTREE_DIRTY(child)) { // add in the child's margin nsMargin margin; child->GetMargin(margin); // obtain our offset from the top left border of the stack's content box. nsSize offset(0,0); PRBool offsetSpecified = AddOffset(aState, child, offset); // Correct the child's x/y position by adding in both the margins // and the left/top offset. childRect.x = clientRect.x + offset.width + margin.left; childRect.y = clientRect.y + offset.height + margin.top; // If we have an offset, we don't stretch the child. Just use // its preferred size. if (offsetSpecified) { nsSize pref = child->GetPrefSize(aState); childRect.width = pref.width; childRect.height = pref.height; } // Now place the child. child->SetBounds(aState, childRect); // Flow the child. child->Layout(aState); // Get the child's new rect. nsRect childRectNoMargin; childRectNoMargin = childRect = child->GetRect(); childRect.Inflate(margin); // Did the child push back on us and get bigger? if (offset.width + childRect.width > clientRect.width) { clientRect.width = childRect.width + offset.width; grow = PR_TRUE; } if (offset.height + childRect.height > clientRect.height) { clientRect.height = childRect.height + offset.height; grow = PR_TRUE; } if (childRectNoMargin != oldRect) { // redraw the new and old positions if the // child moved or resized. // if the new and old rect intersect meaning we just moved a little // then just redraw the union. If they don't intersect (meaning // we moved a good distance) redraw both separately. if (childRectNoMargin.Intersects(oldRect)) { nsRect u; u.UnionRect(oldRect, childRectNoMargin); aBox->Redraw(aState, &u); } else { aBox->Redraw(aState, &oldRect); aBox->Redraw(aState, &childRectNoMargin); } } } child = child->GetNextBox(); } } while (grow); // if some HTML inside us got bigger we need to force ourselves to // get bigger nsRect bounds(aBox->GetRect()); nsMargin bp; aBox->GetBorderAndPadding(bp); clientRect.Inflate(bp); if (clientRect.width > bounds.width || clientRect.height > bounds.height) { if (clientRect.width > bounds.width) bounds.width = clientRect.width; if (clientRect.height > bounds.height) bounds.height = clientRect.height; aBox->SetBounds(aState, bounds); } return NS_OK; }
template<class T> void HTMLElementDisplay<T>::Notify(Notifier *who, NotifyEvent *what) { if (what && (who == mpHtmlElement)) { const WebRect * tmpRect = &(((DisplayElement *)(this))->mRect); switch (what->event) { case NOTIFY_PARENT_STYLE_CHANGE: // intentional fall-through case NOTIFY_FORMAT_STYLE_CHANGE: // intentional fall-through case NOTIFY_STYLE_CHANGE: { WEBC_BOOL invalidated = WEBC_FALSE; PresetWebRect oldRect(tmpRect); if (SetElementStyle()) { oldRect.Or(tmpRect); T::InvalidateRect(&oldRect); invalidated = WEBC_TRUE; } WEBC_UINT16 visible = GetVisibility(); WEBC_UINT16 display = GetUnitType(); WEBC_UINT16 position = GetPosition(); if (InvalidateTUMirror()) { if (!invalidated) { T::Invalidate(); invalidated = WEBC_TRUE; } // GetHTMLParentDisplay will work even if we happen to be // disconnected from the display tree at the moment. DisplayElement *parent = GetHTMLParentDisplay(); if (parent) { NotifyEvent what(NOTIFIER_TYPE_TEXT_UNIT, NOTIFY_STYLE_CHANGE); what.data.oldStyle.display = display; what.data.oldStyle.position = position; parent->Notify((TextUnit *) this, &what); } } if (!invalidated) { if (visible != GetVisibility()) { T::Invalidate(); invalidated = WEBC_TRUE; } } break; } case NOTIFY_PARENT_DISPLAY_STYLE_CHANGE: // intentional fall-through case NOTIFY_DISPLAY_STYLE_CHANGE: { WEBC_BOOL invalidated = WEBC_FALSE; PresetWebRect oldRect(tmpRect); if (SetElementStyle()) { oldRect.Or(tmpRect); T::InvalidateRect(&oldRect); invalidated = WEBC_TRUE; } if (InvalidateVisibility()) { if (!invalidated) { T::Invalidate(); invalidated = WEBC_TRUE; } } if (InvalidateZIndex()) { DisplayElement *parent = GetHTMLParentDisplay(); if (parent) { NotifyEvent what(NOTIFIER_TYPE_TEXT_UNIT, NOTIFY_ZINDEX_CHANGE); parent->Notify((TextUnit*) this, &what); } if (!invalidated) { T::Invalidate(); invalidated = WEBC_TRUE; } } break; } default: break; } } T::Notify(who, what); }
void DisplayManager::SetViewport (WebRect *pViewRect) { if (!mViewRect.Equals(pViewRect)) { PresetWebRect oldRect(&mViewRect); mViewportChanged = WEBC_TRUE; mViewRect.Set(pViewRect); CorrectViewportPosition(); #ifdef WEBC_BUFFER_SCROLLING if (mManagerFlags & MANAGER_FLAG_BUFFER_SCROLL) { WebGraphics* gc = this->GetGraphics(); if (gc) { if (mScrollBuffer == 0) { mScrollBuffer = gc->CreateBuffer(mViewRect.Width() * 2, mViewRect.Height() * 2); } else { if (oldRect.Width() != mViewRect.Width() || oldRect.Height() != mViewRect.Height()) { mScrollBuffer = gc->ResizeBuffer(mScrollBuffer, mViewRect.Width() * 2, mViewRect.Height() * 2); AddDirtyRect(&mViewRect); SetManagerFlag(MANAGER_FLAG_DIRTY); return; } } if (mScrollBuffer) { // find non-overlapping regions if (mViewRect.Overlaps(&oldRect)) { PresetWebRect viewRect(&mViewRect); WebRect extraRect; int count = viewRect.Split(&oldRect, &extraRect); if (count > 0) { if (count > 1) { if (count > 2) { if (!extraRect.Empty()) { AddDirtyRect(&extraRect); } } if (!oldRect.Empty()) { AddDirtyRect(&oldRect); } } if (!viewRect.Empty()) { AddDirtyRect(&viewRect); } } } else { AddDirtyRect(&mViewRect); } SetManagerFlag(MANAGER_FLAG_DIRTY); } } } #endif } }
// More efficient: erase and redraw simultaneously if possible bool wxGenericDragImage::RedrawImage(const wxPoint& oldPos, const wxPoint& newPos, bool eraseOld, bool drawNew) { if (!m_windowDC) return false; #ifdef wxHAS_NATIVE_OVERLAY wxUnusedVar(oldPos); wxDCOverlay dcoverlay( m_overlay, (wxWindowDC*) m_windowDC ) ; if ( eraseOld ) dcoverlay.Clear() ; if (drawNew) DoDrawImage(*m_windowDC, newPos); #else // !wxHAS_NATIVE_OVERLAY wxBitmap* backing = (m_pBackingBitmap ? m_pBackingBitmap : (wxBitmap*) & m_backingBitmap); if (!backing->IsOk()) return false; wxRect oldRect(GetImageRect(oldPos)); wxRect newRect(GetImageRect(newPos)); wxRect fullRect; // Full rect: the combination of both rects if (eraseOld && drawNew) { int oldRight = oldRect.GetRight(); int oldBottom = oldRect.GetBottom(); int newRight = newRect.GetRight(); int newBottom = newRect.GetBottom(); wxPoint topLeft = wxPoint(wxMin(oldPos.x, newPos.x), wxMin(oldPos.y, newPos.y)); wxPoint bottomRight = wxPoint(wxMax(oldRight, newRight), wxMax(oldBottom, newBottom)); fullRect.x = topLeft.x; fullRect.y = topLeft.y; fullRect.SetRight(bottomRight.x); fullRect.SetBottom(bottomRight.y); } else if (eraseOld) fullRect = oldRect; else if (drawNew) fullRect = newRect; // Make the bitmap bigger than it need be, so we don't // keep reallocating all the time. int excess = 50; if (!m_repairBitmap.IsOk() || (m_repairBitmap.GetWidth() < fullRect.GetWidth() || m_repairBitmap.GetHeight() < fullRect.GetHeight())) { m_repairBitmap = wxBitmap(fullRect.GetWidth() + excess, fullRect.GetHeight() + excess); } wxMemoryDC memDC; memDC.SelectObject(* backing); wxMemoryDC memDCTemp; memDCTemp.SelectObject(m_repairBitmap); // Draw the backing bitmap onto the repair bitmap. // If full-screen, we may have specified the rect on the // screen that we're using for our backing bitmap. // So subtract this when we're blitting from the backing bitmap // (translate from screen to backing-bitmap coords). memDCTemp.Blit(0, 0, fullRect.GetWidth(), fullRect.GetHeight(), & memDC, fullRect.x - m_boundingRect.x, fullRect.y - m_boundingRect.y); // If drawing, draw the image onto the mem DC if (drawNew) { wxPoint pos(newPos.x - fullRect.x, newPos.y - fullRect.y) ; DoDrawImage(memDCTemp, pos); } // Now blit to the window // Finally, blit the temp mem DC to the window. m_windowDC->Blit(fullRect.x, fullRect.y, fullRect.width, fullRect.height, & memDCTemp, 0, 0); memDCTemp.SelectObject(wxNullBitmap); memDC.SelectObject(wxNullBitmap); #endif // wxHAS_NATIVE_OVERLAY/!wxHAS_NATIVE_OVERLAY return true; }
NS_IMETHODIMP nsSprocketLayout::Layout(nsIFrame* aBox, nsBoxLayoutState& aState) { // See if we are collapsed. If we are, then simply iterate over all our // children and give them a rect of 0 width and height. if (aBox->IsCollapsed()) { nsIFrame* child = nsBox::GetChildBox(aBox); while(child) { nsBoxFrame::LayoutChildAt(aState, child, nsRect(0,0,0,0)); child = nsBox::GetNextBox(child); } return NS_OK; } nsBoxLayoutState::AutoReflowDepth depth(aState); mozilla::AutoStackArena arena; // ----- figure out our size ---------- const nsSize originalSize = aBox->GetSize(); // -- make sure we remove our border and padding ---- nsRect clientRect; aBox->GetClientRect(clientRect); // |originalClientRect| represents the rect of the entire box (excluding borders // and padding). We store it here because we're going to use |clientRect| to hold // the required size for all our kids. As an example, consider an hbox with a // specified width of 300. If the kids total only 150 pixels of width, then // we have 150 pixels left over. |clientRect| is going to hold a width of 150 and // is going to be adjusted based off the value of the PACK property. If flexible // objects are in the box, then the two rects will match. nsRect originalClientRect(clientRect); // The frame state contains cached knowledge about our box, such as our orientation // and direction. nsFrameState frameState = nsFrameState(0); GetFrameState(aBox, frameState); // Build a list of our children's desired sizes and computed sizes nsBoxSize* boxSizes = nullptr; nsComputedBoxSize* computedBoxSizes = nullptr; nscoord min = 0; nscoord max = 0; int32_t flexes = 0; PopulateBoxSizes(aBox, aState, boxSizes, min, max, flexes); // The |size| variable will hold the total size of children along the axis of // the box. Continuing with the example begun in the comment above, size would // be 150 pixels. nscoord size = clientRect.width; if (!IsHorizontal(aBox)) size = clientRect.height; ComputeChildSizes(aBox, aState, size, boxSizes, computedBoxSizes); // After the call to ComputeChildSizes, the |size| variable contains the // total required size of all the children. We adjust our clientRect in the // appropriate dimension to match this size. In our example, we now assign // 150 pixels into the clientRect.width. // // The variables |min| and |max| hold the minimum required size box must be // in the OPPOSITE orientation, e.g., for a horizontal box, |min| is the minimum // height we require to enclose our children, and |max| is the maximum height // required to enclose our children. if (IsHorizontal(aBox)) { clientRect.width = size; if (clientRect.height < min) clientRect.height = min; if (frameState & NS_STATE_AUTO_STRETCH) { if (clientRect.height > max) clientRect.height = max; } } else { clientRect.height = size; if (clientRect.width < min) clientRect.width = min; if (frameState & NS_STATE_AUTO_STRETCH) { if (clientRect.width > max) clientRect.width = max; } } // With the sizes computed, now it's time to lay out our children. bool finished; nscoord passes = 0; // We flow children at their preferred locations (along with the appropriate computed flex). // After we flow a child, it is possible that the child will change its size. If/when this happens, // we have to do another pass. Typically only 2 passes are required, but the code is prepared to // do as many passes as are necessary to achieve equilibrium. nscoord x = 0; nscoord y = 0; nscoord origX = 0; nscoord origY = 0; // |childResized| lets us know if a child changed its size after we attempted to lay it out at // the specified size. If this happens, we usually have to do another pass. bool childResized = false; // |passes| stores our number of passes. If for any reason we end up doing more than, say, 10 // passes, we assert to indicate that something is seriously screwed up. passes = 0; do { #ifdef DEBUG_REFLOW if (passes > 0) { AddIndents(); printf("ChildResized doing pass: %d\n", passes); } #endif // Always assume that we're done. This will change if, for example, children don't stay // the same size after being flowed. finished = true; // Handle box packing. HandleBoxPack(aBox, frameState, x, y, originalClientRect, clientRect); // Now that packing is taken care of we set up a few additional // tracking variables. origX = x; origY = y; // Now we iterate over our box children and our box size lists in // parallel. For each child, we look at its sizes and figure out // where to place it. nsComputedBoxSize* childComputedBoxSize = computedBoxSizes; nsBoxSize* childBoxSize = boxSizes; nsIFrame* child = nsBox::GetChildBox(aBox); int32_t count = 0; while (child || (childBoxSize && childBoxSize->bogus)) { // If for some reason, our lists are not the same length, we guard // by bailing out of the loop. if (childBoxSize == nullptr) { NS_NOTREACHED("Lists not the same length."); break; } nscoord width = clientRect.width; nscoord height = clientRect.height; if (!childBoxSize->bogus) { // We have a valid box size entry. This entry already contains information about our // sizes along the axis of the box (e.g., widths in a horizontal box). If our default // ALIGN is not stretch, however, then we also need to know the child's size along the // opposite axis. if (!(frameState & NS_STATE_AUTO_STRETCH)) { nsSize prefSize = child->GetPrefSize(aState); nsSize minSize = child->GetMinSize(aState); nsSize maxSize = child->GetMaxSize(aState); prefSize = nsBox::BoundsCheck(minSize, prefSize, maxSize); AddMargin(child, prefSize); width = std::min(prefSize.width, originalClientRect.width); height = std::min(prefSize.height, originalClientRect.height); } } // Obtain the computed size along the axis of the box for this child from the computedBoxSize entry. // We store the result in |width| for horizontal boxes and |height| for vertical boxes. if (frameState & NS_STATE_IS_HORIZONTAL) width = childComputedBoxSize->size; else height = childComputedBoxSize->size; // Adjust our x/y for the left/right spacing. if (frameState & NS_STATE_IS_HORIZONTAL) { if (frameState & NS_STATE_IS_DIRECTION_NORMAL) x += (childBoxSize->left); else x -= (childBoxSize->right); } else { if (frameState & NS_STATE_IS_DIRECTION_NORMAL) y += (childBoxSize->left); else y -= (childBoxSize->right); } // Now we build a child rect. nscoord rectX = x; nscoord rectY = y; if (!(frameState & NS_STATE_IS_DIRECTION_NORMAL)) { if (frameState & NS_STATE_IS_HORIZONTAL) rectX -= width; else rectY -= height; } // We now create an accurate child rect based off our computed size information. nsRect childRect(rectX, rectY, width, height); // Sanity check against our clientRect. It is possible that a child specified // a size that is too large to fit. If that happens, then we have to grow // our client rect. Remember, clientRect is not the total rect of the enclosing // box. It currently holds our perception of how big the children needed to // be. if (childRect.width > clientRect.width) clientRect.width = childRect.width; if (childRect.height > clientRect.height) clientRect.height = childRect.height; // Either |nextX| or |nextY| is updated by this function call, according // to our axis. nscoord nextX = x; nscoord nextY = y; ComputeChildsNextPosition(aBox, x, y, nextX, nextY, childRect); // Now we further update our nextX/Y along our axis. // We also set childRect.y/x along the opposite axis appropriately for a // stretch alignment. (Non-stretch alignment is handled below.) if (frameState & NS_STATE_IS_HORIZONTAL) { if (frameState & NS_STATE_IS_DIRECTION_NORMAL) nextX += (childBoxSize->right); else nextX -= (childBoxSize->left); childRect.y = originalClientRect.y; } else { if (frameState & NS_STATE_IS_DIRECTION_NORMAL) nextY += (childBoxSize->right); else nextY -= (childBoxSize->left); childRect.x = originalClientRect.x; } // If we encounter a completely bogus box size, we just leave this child completely // alone and continue through the loop to the next child. if (childBoxSize->bogus) { childComputedBoxSize = childComputedBoxSize->next; childBoxSize = childBoxSize->next; count++; x = nextX; y = nextY; continue; } nsMargin margin(0,0,0,0); bool layout = true; // Deflate the rect of our child by its margin. child->GetMargin(margin); childRect.Deflate(margin); if (childRect.width < 0) childRect.width = 0; if (childRect.height < 0) childRect.height = 0; // Now we're trying to figure out if we have to lay out this child, i.e., to call // the child's Layout method. if (passes > 0) { layout = false; } else { // Always perform layout if we are dirty or have dirty children if (!NS_SUBTREE_DIRTY(child)) layout = false; } nsRect oldRect(child->GetRect()); // Non-stretch alignment will be handled in AlignChildren(), so don't // change child out-of-axis positions yet. if (!(frameState & NS_STATE_AUTO_STRETCH)) { if (frameState & NS_STATE_IS_HORIZONTAL) { childRect.y = oldRect.y; } else { childRect.x = oldRect.x; } } // We computed a childRect. Now we want to set the bounds of the child to be that rect. // If our old rect is different, then we know our size changed and we cache that fact // in the |sizeChanged| variable. child->SetBounds(aState, childRect); bool sizeChanged = (childRect.width != oldRect.width || childRect.height != oldRect.height); if (sizeChanged) { // Our size is different. Sanity check against our maximum allowed size to ensure // we didn't exceed it. nsSize minSize = child->GetMinSize(aState); nsSize maxSize = child->GetMaxSize(aState); maxSize = nsBox::BoundsCheckMinMax(minSize, maxSize); // make sure the size is in our max size. if (childRect.width > maxSize.width) childRect.width = maxSize.width; if (childRect.height > maxSize.height) childRect.height = maxSize.height; // set it again child->SetBounds(aState, childRect); } // If we already determined that layout was required or if our size has changed, then // we make sure to call layout on the child, since its children may need to be shifted // around as a result of the size change. if (layout || sizeChanged) child->Layout(aState); // If the child was a block or inline (e.g., HTML) it may have changed its rect *during* layout. // We have to check for this. nsRect newChildRect(child->GetRect()); if (!newChildRect.IsEqualInterior(childRect)) { #ifdef DEBUG_GROW child->DumpBox(stdout); printf(" GREW from (%d,%d) -> (%d,%d)\n", childRect.width, childRect.height, newChildRect.width, newChildRect.height); #endif newChildRect.Inflate(margin); childRect.Inflate(margin); // The child changed size during layout. The ChildResized method handles this // scenario. ChildResized(aBox, aState, child, childBoxSize, childComputedBoxSize, boxSizes, computedBoxSizes, childRect, newChildRect, clientRect, flexes, finished); // We note that a child changed size, which means that another pass will be required. childResized = true; // Now that a child resized, it's entirely possible that OUR rect is too small. Now we // ensure that |originalClientRect| is grown to accommodate the size of |clientRect|. if (clientRect.width > originalClientRect.width) originalClientRect.width = clientRect.width; if (clientRect.height > originalClientRect.height) originalClientRect.height = clientRect.height; if (!(frameState & NS_STATE_IS_DIRECTION_NORMAL)) { // Our childRect had its XMost() or YMost() (depending on our layout // direction), positioned at a certain point. Ensure that the // newChildRect satisfies the same constraint. Note that this is // just equivalent to adjusting the x/y by the difference in // width/height between childRect and newChildRect. So we don't need // to reaccount for the left and right of the box layout state again. if (frameState & NS_STATE_IS_HORIZONTAL) newChildRect.x = childRect.XMost() - newChildRect.width; else newChildRect.y = childRect.YMost() - newChildRect.height; } // If the child resized then recompute its position. ComputeChildsNextPosition(aBox, x, y, nextX, nextY, newChildRect); if (newChildRect.width >= margin.left + margin.right && newChildRect.height >= margin.top + margin.bottom) newChildRect.Deflate(margin); if (childRect.width >= margin.left + margin.right && childRect.height >= margin.top + margin.bottom) childRect.Deflate(margin); child->SetBounds(aState, newChildRect); // If we are the first box that changed size, then we don't need to do a second pass if (count == 0) finished = true; } // Now update our x/y finally. x = nextX; y = nextY; // Move to the next child. childComputedBoxSize = childComputedBoxSize->next; childBoxSize = childBoxSize->next; child = nsBox::GetNextBox(child); count++; } // Sanity-checking code to ensure we don't do an infinite # of passes. passes++; NS_ASSERTION(passes < 10, "A Box's child is constantly growing!!!!!"); if (passes > 10) break; } while (false == finished); // Get rid of our size lists. while(boxSizes) { nsBoxSize* toDelete = boxSizes; boxSizes = boxSizes->next; delete toDelete; } while(computedBoxSizes) { nsComputedBoxSize* toDelete = computedBoxSizes; computedBoxSizes = computedBoxSizes->next; delete toDelete; } if (childResized) { // See if one of our children forced us to get bigger nsRect tmpClientRect(originalClientRect); nsMargin bp(0,0,0,0); aBox->GetBorderAndPadding(bp); tmpClientRect.Inflate(bp); if (tmpClientRect.width > originalSize.width || tmpClientRect.height > originalSize.height) { // if it did reset our bounds. nsRect bounds(aBox->GetRect()); if (tmpClientRect.width > originalSize.width) bounds.width = tmpClientRect.width; if (tmpClientRect.height > originalSize.height) bounds.height = tmpClientRect.height; aBox->SetBounds(aState, bounds); } } // Because our size grew, we now have to readjust because of box packing. Repack // in order to update our x and y to the correct values. HandleBoxPack(aBox, frameState, x, y, originalClientRect, clientRect); // Compare against our original x and y and only worry about adjusting the children if // we really did have to change the positions because of packing (typically for 'center' // or 'end' pack values). if (x != origX || y != origY) { nsIFrame* child = nsBox::GetChildBox(aBox); // reposition all our children while (child) { nsRect childRect(child->GetRect()); childRect.x += (x - origX); childRect.y += (y - origY); child->SetBounds(aState, childRect); child = nsBox::GetNextBox(child); } } // Perform out-of-axis alignment for non-stretch alignments if (!(frameState & NS_STATE_AUTO_STRETCH)) { AlignChildren(aBox, aState); } // That's it! If you made it this far without having a nervous breakdown, // congratulations! Go get yourself a beer. return NS_OK; }
void ScrollView::updateScrollbars(const IntSize& desiredOffset) { // Don't allow re-entrancy into this function. if (m_data->m_inUpdateScrollbars) return; // FIXME: This code is here so we don't have to fork FrameView.h/.cpp. // In the end, FrameView should just merge with ScrollView. if (static_cast<const FrameView*>(this)->frame()->prohibitsScrolling()) return; m_data->m_inUpdateScrollbars = true; bool hasVerticalScrollbar = m_data->m_vBar; bool hasHorizontalScrollbar = m_data->m_hBar; bool oldHasVertical = hasVerticalScrollbar; bool oldHasHorizontal = hasHorizontalScrollbar; ScrollbarMode hScroll = m_data->m_hScrollbarMode; ScrollbarMode vScroll = m_data->m_vScrollbarMode; const int cVerticalWidth = PlatformScrollbar::verticalScrollbarWidth(); const int cHorizontalHeight = PlatformScrollbar::horizontalScrollbarHeight(); for (int pass = 0; pass < 2; pass++) { bool scrollsVertically; bool scrollsHorizontally; if (!m_data->m_scrollbarsSuppressed && (hScroll == ScrollbarAuto || vScroll == ScrollbarAuto)) { // Do a layout if pending before checking if scrollbars are needed. if (hasVerticalScrollbar != oldHasVertical || hasHorizontalScrollbar != oldHasHorizontal) static_cast<FrameView*>(this)->layout(); scrollsVertically = (vScroll == ScrollbarAlwaysOn) || (vScroll == ScrollbarAuto && contentsHeight() > height()); if (scrollsVertically) scrollsHorizontally = (hScroll == ScrollbarAlwaysOn) || (hScroll == ScrollbarAuto && contentsWidth() + cVerticalWidth > width()); else { scrollsHorizontally = (hScroll == ScrollbarAlwaysOn) || (hScroll == ScrollbarAuto && contentsWidth() > width()); if (scrollsHorizontally) scrollsVertically = (vScroll == ScrollbarAlwaysOn) || (vScroll == ScrollbarAuto && contentsHeight() + cHorizontalHeight > height()); } } else { scrollsHorizontally = (hScroll == ScrollbarAuto) ? hasHorizontalScrollbar : (hScroll == ScrollbarAlwaysOn); scrollsVertically = (vScroll == ScrollbarAuto) ? hasVerticalScrollbar : (vScroll == ScrollbarAlwaysOn); } if (hasVerticalScrollbar != scrollsVertically) { m_data->setHasVerticalScrollbar(scrollsVertically); hasVerticalScrollbar = scrollsVertically; } if (hasHorizontalScrollbar != scrollsHorizontally) { m_data->setHasHorizontalScrollbar(scrollsHorizontally); hasHorizontalScrollbar = scrollsHorizontally; } } // Set up the range (and page step/line step). IntSize maxScrollPosition(contentsWidth() - visibleWidth(), contentsHeight() - visibleHeight()); IntSize scroll = desiredOffset.shrunkTo(maxScrollPosition); scroll.clampNegativeToZero(); if (m_data->m_hBar) { int clientWidth = visibleWidth(); m_data->m_hBar->setEnabled(contentsWidth() > clientWidth); int pageStep = (clientWidth - PAGE_KEEP); if (pageStep < 0) pageStep = clientWidth; IntRect oldRect(m_data->m_hBar->frameGeometry()); IntRect hBarRect = IntRect(0, height() - m_data->m_hBar->height(), width() - (m_data->m_vBar ? m_data->m_vBar->width() : 0), m_data->m_hBar->height()); m_data->m_hBar->setRect(hBarRect); if (!m_data->m_scrollbarsSuppressed && oldRect != m_data->m_hBar->frameGeometry()) m_data->m_hBar->invalidate(); if (m_data->m_scrollbarsSuppressed) m_data->m_hBar->setSuppressInvalidation(true); m_data->m_hBar->setSteps(LINE_STEP, pageStep); m_data->m_hBar->setProportion(clientWidth, contentsWidth()); m_data->m_hBar->setValue(scroll.width()); if (m_data->m_scrollbarsSuppressed) m_data->m_hBar->setSuppressInvalidation(false); } if (m_data->m_vBar) { int clientHeight = visibleHeight(); m_data->m_vBar->setEnabled(contentsHeight() > clientHeight); int pageStep = (clientHeight - PAGE_KEEP); if (pageStep < 0) pageStep = clientHeight; IntRect oldRect(m_data->m_vBar->frameGeometry()); IntRect vBarRect = IntRect(width() - m_data->m_vBar->width(), 0, m_data->m_vBar->width(), height() - (m_data->m_hBar ? m_data->m_hBar->height() : 0)); m_data->m_vBar->setRect(vBarRect); if (!m_data->m_scrollbarsSuppressed && oldRect != m_data->m_vBar->frameGeometry()) m_data->m_vBar->invalidate(); if (m_data->m_scrollbarsSuppressed) m_data->m_vBar->setSuppressInvalidation(true); m_data->m_vBar->setSteps(LINE_STEP, pageStep); m_data->m_vBar->setProportion(clientHeight, contentsHeight()); m_data->m_vBar->setValue(scroll.height()); if (m_data->m_scrollbarsSuppressed) m_data->m_vBar->setSuppressInvalidation(false); } if (oldHasVertical != (m_data->m_vBar != 0) || oldHasHorizontal != (m_data->m_hBar != 0)) geometryChanged(); // See if our offset has changed in a situation where we might not have scrollbars. // This can happen when editing a body with overflow:hidden and scrolling to reveal selection. // It can also happen when maximizing a window that has scrollbars (but the new maximized result // does not). IntSize scrollDelta = scroll - m_data->m_scrollOffset; if (scrollDelta != IntSize()) { m_data->m_scrollOffset = scroll; m_data->scrollBackingStore(scrollDelta); } m_data->m_inUpdateScrollbars = false; }