mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-13 18:27:35 +00:00
276 lines
8.7 KiB
C++
276 lines
8.7 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||
*
|
||
* The contents of this file are subject to the Netscape Public License
|
||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||
* http://www.mozilla.org/NPL/
|
||
*
|
||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||
* for the specific language governing rights and limitations under the
|
||
* NPL.
|
||
*
|
||
* The Initial Developer of this code under the NPL is Netscape
|
||
* Communications Corporation. Portions created by Netscape are
|
||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||
* Reserved.
|
||
*/
|
||
|
||
// CToolbarPatternBevelView.cp
|
||
|
||
#include <LArrayIterator.h>
|
||
|
||
#include "CToolbarPatternBevelView.h"
|
||
#include "CToolbarButton.h"
|
||
#include "StRegionHandle.h"
|
||
|
||
#include <stddef.h>
|
||
|
||
// Bug #79175
|
||
// Change the update command status so that the "Show/Hide Component Bar" works
|
||
CToolbarPatternBevelView::CToolbarPatternBevelView(LStream* inStream)
|
||
: CPatternBevelView(inStream)
|
||
{
|
||
LCommander::SetUpdateCommandStatus(true);
|
||
}
|
||
|
||
// Bug #79175
|
||
// Change the update command status so that the "Show/Hide Component Bar" works
|
||
CToolbarPatternBevelView::~CToolbarPatternBevelView()
|
||
{
|
||
LCommander::SetUpdateCommandStatus(true);
|
||
}
|
||
|
||
void CToolbarPatternBevelView::HandleModeChange( Int8 inNewMode, SDimension16& outSizeChange )
|
||
{
|
||
CalcArrangement(false, inNewMode, outSizeChange);
|
||
}
|
||
|
||
void CToolbarPatternBevelView::RotateArrangement( SDimension16& outSizeChange )
|
||
{
|
||
CalcArrangement(true, Int8(), outSizeChange);
|
||
}
|
||
|
||
void CToolbarPatternBevelView::CalcArrangement( Boolean inRotateArrangement, Int8 inNewMode, SDimension16& outSizeChange)
|
||
/*
|
||
Note: either rotates the arrangement _or else_ changes the mode, but not both.
|
||
|
||
...treats |CToolbarButtons| sub-views as though they are layed out in a grid
|
||
whose cell-size is the maximum height and width of any of them. In a mode change,
|
||
their sizes change, the grid must be recalculated, and the buttons moved
|
||
appropriately.
|
||
*/
|
||
{
|
||
size_t number_of_buttons = 0;
|
||
SDimension16 old_cell_size={ 0, 0 }, new_cell_size={ 0, 0 };
|
||
SDimension16 grid_origin;
|
||
|
||
/*
|
||
Iterate over the |CToolbarButtons| within me, _twice_...
|
||
*/
|
||
|
||
// ...once to calculate the old and new grid cell-size, and change the mode of each button;
|
||
LPane* current_subview_ptr = 0;
|
||
for ( LArrayIterator iter(mSubPanes); iter.Next(¤t_subview_ptr); )
|
||
if ( CToolbarButton* button = dynamic_cast<CToolbarButton*>(current_subview_ptr) )
|
||
{
|
||
++number_of_buttons;
|
||
|
||
SDimension16 button_size;
|
||
|
||
// Use the pre-ChangeMode size of this button to calculate |old_cell_size|
|
||
button->GetFrameSize(button_size);
|
||
|
||
|
||
/*
|
||
The origin of the grid is the remainder when dividing the maximum sized
|
||
cells offset by its size (independently for x and y).
|
||
*/
|
||
|
||
Boolean recalc_origin_x = button_size.width > old_cell_size.width;
|
||
Boolean recalc_origin_y = button_size.height > old_cell_size.height;
|
||
|
||
if ( recalc_origin_x || recalc_origin_y )
|
||
{
|
||
Rect button_rect;
|
||
button->CalcLocalFrameRect(button_rect);
|
||
|
||
if ( recalc_origin_x )
|
||
{
|
||
old_cell_size.width = button_size.width;
|
||
grid_origin.width = button_rect.left - (button_size.width * (button_rect.left / button_size.width));
|
||
}
|
||
else // recalc_origin_y
|
||
{
|
||
old_cell_size.height = button_size.height;
|
||
grid_origin.height = button_rect.top - (button_size.height * (button_rect.top / button_size.height));
|
||
}
|
||
}
|
||
|
||
|
||
if ( !inRotateArrangement )
|
||
{
|
||
button->ChangeMode(inNewMode, SDimension16());
|
||
|
||
// ...and the post-ChangeMode size for |new_cell_size|
|
||
button->GetFrameSize(button_size);
|
||
if ( new_cell_size.width < button_size.width )
|
||
new_cell_size.width = button_size.width;
|
||
if ( new_cell_size.height < button_size.height )
|
||
new_cell_size.height = button_size.height;
|
||
}
|
||
}
|
||
|
||
if ( inRotateArrangement )
|
||
new_cell_size = old_cell_size;
|
||
|
||
|
||
Int16 number_of_columns = 0;
|
||
Int16 number_of_rows = 0;
|
||
|
||
// ...and again (if buttons were found in the first pass) to actually move them.
|
||
if ( number_of_buttons > 0 )
|
||
{
|
||
for ( LArrayIterator iter(mSubPanes); (number_of_buttons > 0) && iter.Next(¤t_subview_ptr); )
|
||
if ( CToolbarButton* button = dynamic_cast<CToolbarButton*>(current_subview_ptr) )
|
||
{
|
||
--number_of_buttons;
|
||
|
||
// Determine which cell this button occupies. It hasn't been moved yet, so use |old_cell_size|, and the buttons top-left.
|
||
Rect button_rect;
|
||
button->CalcLocalFrameRect(button_rect);
|
||
Int16 column = (button_rect.left - grid_origin.width) / old_cell_size.width;
|
||
Int16 row = (button_rect.top - grid_origin.height) / old_cell_size.height;
|
||
|
||
if ( inRotateArrangement )
|
||
{
|
||
Int16 temp = column;
|
||
column = row;
|
||
row = temp;
|
||
}
|
||
|
||
if ( number_of_columns <= column )
|
||
number_of_columns = column + 1;
|
||
if ( number_of_rows <= row )
|
||
number_of_rows = row + 1;
|
||
|
||
// Calculate the padding needed to center this button within a (new-size) cell.
|
||
SDimension16 button_size;
|
||
button->GetFrameSize(button_size);
|
||
Int16 horizontal_padding = (new_cell_size.width - button_size.width) / 2;
|
||
Int16 vertical_padding = (new_cell_size.height - button_size.height) / 2;
|
||
|
||
// Calculate the buttons new position within its superview (i.e., within |me|)
|
||
Int32 x = grid_origin.width + (column * new_cell_size.width) + horizontal_padding;
|
||
Int32 y = grid_origin.height + (row * new_cell_size.height) + vertical_padding;
|
||
|
||
button->PlaceInSuperFrameAt(x, y, true); // ...only moves if it has to
|
||
}
|
||
}
|
||
|
||
Int16 old_number_of_columns = inRotateArrangement ? number_of_rows : number_of_columns;
|
||
Int16 old_number_of_rows = inRotateArrangement ? number_of_columns : number_of_rows;
|
||
|
||
outSizeChange.width = (number_of_columns * new_cell_size.width) - (old_number_of_columns * old_cell_size.width);
|
||
outSizeChange.height = (number_of_rows * new_cell_size.height) - (old_number_of_rows * old_cell_size.height);
|
||
}
|
||
|
||
#pragma mark -
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
// <09> FocusDraw
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
// Set up coordinates system and clipping region
|
||
//
|
||
// Panes rely on their superview to focus them. When a Pane requests
|
||
// focus for drawing, we set the clipping region to the revealed
|
||
// portion of that Pane's Frame minus the Frames of all sibling Panes
|
||
// that are in front of that Pane.
|
||
|
||
Boolean
|
||
CToolbarPatternBevelView::FocusDraw(
|
||
LPane *inSubPane)
|
||
{
|
||
Boolean revealed = true;
|
||
|
||
if (inSubPane == nil) { // Focus this view
|
||
revealed = LView::FocusDraw();
|
||
|
||
} else { // Focus a SubPane
|
||
|
||
if (EstablishPort()) { // Set current Mac Port
|
||
sInFocusView = nil; // Saved focus is now invalid
|
||
|
||
// Set up local coordinate system
|
||
::SetOrigin(mPortOrigin.h, mPortOrigin.v);
|
||
|
||
// Build clipping region
|
||
|
||
// Start with the intersection of the
|
||
// revealed rect of this View with the
|
||
// Frame of the SubPane
|
||
Rect subRect;
|
||
inSubPane->CalcPortFrameRect(subRect);
|
||
|
||
if (!::SectRect(&subRect, &mRevealedRect, &subRect)) {
|
||
// No intersection, so subpane is
|
||
// not revealed. Set empty clip.
|
||
::ClipRect(&subRect);
|
||
return false;
|
||
}
|
||
|
||
// SubPane is revealed. Make region
|
||
// from the intersection.
|
||
StRegionHandle clipR;
|
||
::RectRgn(clipR, &subRect);
|
||
|
||
// Determine first sibling which is in front of this SubPane.
|
||
ArrayIndexT subIndex = 0;
|
||
LPane* thePane = nil;
|
||
|
||
{
|
||
LArrayIterator iterator(mSubPanes, LArrayIterator::from_Start);
|
||
while (iterator.Next(&thePane))
|
||
{
|
||
subIndex++;
|
||
if (thePane == inSubPane)
|
||
break;
|
||
}
|
||
}
|
||
|
||
// Subtract Frames of all sibling Panes (which are visible)
|
||
// that are in front of this SubPane (i.e., come after the
|
||
// SubPane in this View's list of SubPanes.
|
||
|
||
StRegionHandle siblingR;
|
||
LArrayIterator iterator(mSubPanes, subIndex);
|
||
Rect siblingFrame;
|
||
|
||
while (iterator.Next(&thePane))
|
||
{
|
||
if (thePane->IsVisible() && thePane->CalcPortFrameRect(siblingFrame))
|
||
{
|
||
// Subtract sibling's Frame from
|
||
// the clipping region
|
||
::RectRgn(siblingR, &siblingFrame);
|
||
::DiffRgn(clipR, siblingR, clipR);
|
||
}
|
||
}
|
||
|
||
// Convert Clip region from Port to
|
||
// Local coords and set it
|
||
::OffsetRgn(clipR, mPortOrigin.h, mPortOrigin.v);
|
||
::SetClip(clipR);
|
||
|
||
revealed = !::EmptyRgn(clipR);
|
||
|
||
} else {
|
||
SignalPStr_("\pFocus View with no GrafPort");
|
||
revealed = false;
|
||
}
|
||
|
||
}
|
||
|
||
return revealed;
|
||
}
|