Autoscrolling menus feature landing #32730

-r hyatt, saari
This commit is contained in:
evaughan%netscape.com 2000-06-23 05:15:04 +00:00
Родитель 95adc8b187
Коммит 969d067559
58 изменённых файлов: 2659 добавлений и 829 удалений

Просмотреть файл

@ -50,7 +50,7 @@ static char* mEventNames[] = {
"submit", "reset", "change", "select", "input", "paint" ,"text",
"create", "close", "destroy", "command", "broadcast", "commandupdate",
"dragenter", "dragover", "dragexit", "dragdrop", "draggesture", "resize",
"scroll"
"scroll","overflow", "underflow"
};
nsDOMEvent::nsDOMEvent(nsIPresContext* aPresContext, nsEvent* aEvent, const nsString& aEventType) {
@ -311,29 +311,48 @@ nsDOMEvent::GetDetail(PRInt32* aDetail)
{
//detail is valid for more than just mouseevents but we don't
//use it for anything else right now
if (!mEvent || mEvent->eventStructType != NS_MOUSE_EVENT) {
if (!mEvent) {
*aDetail = 0;
return NS_OK;
}
switch (mEvent->message) {
case NS_MOUSE_LEFT_BUTTON_UP:
case NS_MOUSE_LEFT_BUTTON_DOWN:
case NS_MOUSE_LEFT_CLICK:
case NS_MOUSE_LEFT_DOUBLECLICK:
case NS_MOUSE_MIDDLE_BUTTON_UP:
case NS_MOUSE_MIDDLE_BUTTON_DOWN:
case NS_MOUSE_MIDDLE_CLICK:
case NS_MOUSE_MIDDLE_DOUBLECLICK:
case NS_MOUSE_RIGHT_BUTTON_UP:
case NS_MOUSE_RIGHT_BUTTON_DOWN:
case NS_MOUSE_RIGHT_CLICK:
case NS_MOUSE_RIGHT_DOUBLECLICK:
*aDetail = ((nsMouseEvent*)mEvent)->clickCount;
break;
default:
break;
switch(mEvent->eventStructType)
{
case NS_SCROLLPORT_EVENT:
{
nsScrollPortEvent* scrollEvent = (nsScrollPortEvent*)mEvent;
*aDetail = (PRInt32)scrollEvent->orient;
return NS_OK;
}
case NS_MOUSE_EVENT:
{
switch (mEvent->message) {
case NS_MOUSE_LEFT_BUTTON_UP:
case NS_MOUSE_LEFT_BUTTON_DOWN:
case NS_MOUSE_LEFT_CLICK:
case NS_MOUSE_LEFT_DOUBLECLICK:
case NS_MOUSE_MIDDLE_BUTTON_UP:
case NS_MOUSE_MIDDLE_BUTTON_DOWN:
case NS_MOUSE_MIDDLE_CLICK:
case NS_MOUSE_MIDDLE_DOUBLECLICK:
case NS_MOUSE_RIGHT_BUTTON_UP:
case NS_MOUSE_RIGHT_BUTTON_DOWN:
case NS_MOUSE_RIGHT_CLICK:
case NS_MOUSE_RIGHT_DOUBLECLICK:
*aDetail = ((nsMouseEvent*)mEvent)->clickCount;
break;
default:
break;
}
}
default:
*aDetail = 0;
return NS_OK;
}
return NS_OK;
}
@ -1123,6 +1142,10 @@ const char* nsDOMEvent::GetEventName(PRUint32 aEventType)
return mEventNames[eDOMEvents_dragdrop];
case NS_DRAGDROP_GESTURE:
return mEventNames[eDOMEvents_draggesture];
case NS_SCROLLPORT_OVERFLOW:
return mEventNames[eDOMEvents_overflow];
case NS_SCROLLPORT_UNDERFLOW:
return mEventNames[eDOMEvents_underflow];
default:
break;
}

Просмотреть файл

@ -84,7 +84,9 @@ public:
eDOMEvents_dragdrop,
eDOMEvents_draggesture,
eDOMEvents_resize,
eDOMEvents_scroll
eDOMEvents_scroll,
eDOMEvents_overflow,
eDOMEvents_underflow
};
nsDOMEvent(nsIPresContext* aPresContext, nsEvent* aEvent, const nsString& aEventType);

Просмотреть файл

@ -450,6 +450,14 @@ nsresult nsEventListenerManager::GetIdentifiersForType(nsIAtom* aType, nsIID& aI
aIID = kIDOMMenuListenerIID;
*aFlags = NS_EVENT_BITS_XUL_COMMAND_UPDATE;
}
else if (aType == nsLayoutAtoms::onoverflow) {
aIID = kIDOMMenuListenerIID;
*aFlags = NS_EVENT_BITS_SCROLLPORT_OVERFLOW;
}
else if (aType == nsLayoutAtoms::onunderflow) {
aIID = kIDOMMenuListenerIID;
*aFlags = NS_EVENT_BITS_SCROLLPORT_UNDERFLOW;
}
else if (aType == nsLayoutAtoms::ondragenter) {
aIID = NS_GET_IID(nsIDOMDragListener);
*aFlags = NS_EVENT_BITS_DRAG_ENTER;
@ -1479,6 +1487,8 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext,
case NS_MENU_DESTROY:
case NS_MENU_ACTION:
case NS_XUL_BROADCAST:
case NS_SCROLLPORT_OVERFLOW:
case NS_SCROLLPORT_UNDERFLOW:
case NS_XUL_COMMAND_UPDATE:
if (nsnull != mMenuListeners) {
if (nsnull == *aDOMEvent) {
@ -1509,6 +1519,12 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext,
case NS_XUL_BROADCAST:
ret = mMenuListener->Broadcast(*aDOMEvent);
break;
case NS_SCROLLPORT_OVERFLOW:
ret = mMenuListener->Overflow(*aDOMEvent);
break;
case NS_SCROLLPORT_UNDERFLOW:
ret = mMenuListener->Underflow(*aDOMEvent);
break;
case NS_XUL_COMMAND_UPDATE:
ret = mMenuListener->CommandUpdate(*aDOMEvent);
break;
@ -1551,6 +1567,18 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext,
correctSubType = PR_TRUE;
}
break;
case NS_SCROLLPORT_OVERFLOW:
subType = NS_EVENT_BITS_SCROLLPORT_OVERFLOW;
if (ls->mSubType & NS_EVENT_BITS_SCROLLPORT_OVERFLOW) {
correctSubType = PR_TRUE;
}
break;
case NS_SCROLLPORT_UNDERFLOW:
subType = NS_EVENT_BITS_SCROLLPORT_UNDERFLOW;
if (ls->mSubType & NS_EVENT_BITS_SCROLLPORT_UNDERFLOW) {
correctSubType = PR_TRUE;
}
break;
case NS_XUL_COMMAND_UPDATE:
subType = NS_EVENT_BITS_XUL_COMMAND_UPDATE;
if (ls->mSubType & NS_EVENT_BITS_XUL_COMMAND_UPDATE) {

Просмотреть файл

@ -213,13 +213,15 @@ protected:
#define NS_EVENT_BITS_LOAD_ERROR 0x08
//nsIDOMMenuListener
#define NS_EVENT_BITS_MENU_NONE 0x00
#define NS_EVENT_BITS_MENU_CREATE 0x01
#define NS_EVENT_BITS_XUL_CLOSE 0x02
#define NS_EVENT_BITS_MENU_DESTROY 0x04
#define NS_EVENT_BITS_MENU_ACTION 0x08
#define NS_EVENT_BITS_XUL_BROADCAST 0x10
#define NS_EVENT_BITS_XUL_COMMAND_UPDATE 0x20
#define NS_EVENT_BITS_MENU_NONE 0x00
#define NS_EVENT_BITS_MENU_CREATE 0x01
#define NS_EVENT_BITS_XUL_CLOSE 0x02
#define NS_EVENT_BITS_MENU_DESTROY 0x04
#define NS_EVENT_BITS_MENU_ACTION 0x08
#define NS_EVENT_BITS_XUL_BROADCAST 0x10
#define NS_EVENT_BITS_XUL_COMMAND_UPDATE 0x20
#define NS_EVENT_BITS_SCROLLPORT_OVERFLOW 0x40
#define NS_EVENT_BITS_SCROLLPORT_UNDERFLOW 0x80
//nsIDOMDragListener
#define NS_EVENT_BITS_DRAG_NONE 0x00

Просмотреть файл

@ -159,6 +159,11 @@ LAYOUT_ATOM(onselect, "onselect")
LAYOUT_ATOM(onsubmit, "onsubmit")
LAYOUT_ATOM(onunload, "onunload")
// scrolling
LAYOUT_ATOM(onoverflow, "onoverflow")
LAYOUT_ATOM(onunderflow, "onunderflow")
#ifdef DEBUG
// Alphabetical list of atoms used by debugging code
LAYOUT_ATOM(cellMap, "TableCellMap")

Просмотреть файл

@ -98,13 +98,19 @@ XUL_ATOM(titledbutton, "titledbutton")
XUL_ATOM(crop, "crop")
XUL_ATOM(mode, "mode")
XUL_ATOM(equalsize, "equalsize")
XUL_ATOM(box, "box")
XUL_ATOM(hbox, "hbox")
XUL_ATOM(vbox, "vbox")
XUL_ATOM(scrollbox, "scrollbox")
XUL_ATOM(mousethrough, "mousethrough")
XUL_ATOM(flex, "flex")
XUL_ATOM(spring, "spring")
XUL_ATOM(orient, "orient")
XUL_ATOM(autostretch, "autostretch")
XUL_ATOM(autorepeatbutton, "autorepeatbutton")
XUL_ATOM(titledbox, "titledbox")
XUL_ATOM(title, "title")
XUL_ATOM(titledboxContentPseudo, ":titledbox-content")

Просмотреть файл

@ -184,6 +184,8 @@ nsXBLBinding::kEventHandlerMap[] = {
{ "command", nsnull, &NS_GET_IID(nsIDOMMenuListener) },
{ "broadcast", nsnull, &NS_GET_IID(nsIDOMMenuListener) },
{ "commandupdate", nsnull, &NS_GET_IID(nsIDOMMenuListener) },
{ "overflow", nsnull, &NS_GET_IID(nsIDOMMenuListener) },
{ "underflow", nsnull, &NS_GET_IID(nsIDOMMenuListener) },
{ "focus", nsnull, &NS_GET_IID(nsIDOMFocusListener) },
{ "blur", nsnull, &NS_GET_IID(nsIDOMFocusListener) },
@ -1428,7 +1430,9 @@ PRBool
nsXBLBinding::IsXULHandler(const nsString& aName)
{
return ((aName.EqualsWithConversion("create")) || (aName.EqualsWithConversion("destroy")) || (aName.EqualsWithConversion("broadcast")) ||
(aName.EqualsWithConversion("command")) || (aName.EqualsWithConversion("commandupdate")) || (aName.EqualsWithConversion("close")));
(aName.EqualsWithConversion("command")) || (aName.EqualsWithConversion("commandupdate")) || (aName.EqualsWithConversion("close")) ||
(aName.EqualsWithConversion("overflow")) ||
(aName.EqualsWithConversion("underflow")) );
}
NS_IMETHODIMP

Просмотреть файл

@ -275,6 +275,24 @@ nsresult nsXBLEventHandler::CommandUpdate(nsIDOMEvent* aEvent)
return NS_OK;
}
nsresult nsXBLEventHandler::Overflow(nsIDOMEvent* aEvent)
{
if (!mEventName.EqualsWithConversion("overflow"))
return NS_OK;
ExecuteHandler(NS_ConvertASCIItoUCS2("overflow"), aEvent);
return NS_OK;
}
nsresult nsXBLEventHandler::Underflow(nsIDOMEvent* aEvent)
{
if (!mEventName.EqualsWithConversion("underflow"))
return NS_OK;
ExecuteHandler(NS_ConvertASCIItoUCS2("underflow"), aEvent);
return NS_OK;
}
nsresult nsXBLEventHandler::Destroy(nsIDOMEvent* aEvent)
{
if (!mEventName.EqualsWithConversion("destroy"))

Просмотреть файл

@ -70,6 +70,8 @@ public:
NS_IMETHOD Action(nsIDOMEvent* aEvent);
NS_IMETHOD Broadcast(nsIDOMEvent* aEvent);
NS_IMETHOD CommandUpdate(nsIDOMEvent* aEvent);
NS_IMETHOD Overflow(nsIDOMEvent* aEvent);
NS_IMETHOD Underflow(nsIDOMEvent* aEvent);
NS_DECL_ISUPPORTS

Просмотреть файл

@ -84,3 +84,4 @@ NS_XULATOM(value);
NS_XULATOM(width);
NS_XULATOM(window);
NS_XULATOM(xulcontentsgenerated);
NS_XULATOM(scrollbox);

Просмотреть файл

@ -344,6 +344,7 @@ nsXULElement::Init()
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF service");
if (NS_FAILED(rv)) return rv;
rv = nsComponentManager::CreateInstance(kNameSpaceManagerCID,
nsnull,
kINameSpaceManagerIID,
@ -397,6 +398,7 @@ nsXULElement::~nsXULElement()
gRDFService = nsnull;
}
NS_IF_RELEASE(gNameSpaceManager);
if (gXULUtils) {
@ -4035,6 +4037,9 @@ nsXULElement::GetBoxObject(nsIBoxObject** aResult)
progID += "-popupset";
else if (tag.get() == nsXULAtoms::tree)
progID += "-tree";
else if (tag.get() == nsXULAtoms::scrollbox)
progID += "-scrollbox";
mBoxObject = do_CreateInstance(progID);
if (!mBoxObject)

Просмотреть файл

@ -330,6 +330,7 @@ protected:
static PRInt32 kNameSpaceID_RDF;
static PRInt32 kNameSpaceID_XUL;
public:
static nsresult
Create(nsXULPrototypeElement* aPrototype, nsIDocument* aDocument, PRBool aIsScriptable, nsIContent** aResult);

Просмотреть файл

@ -218,6 +218,8 @@ nsXULContentUtils::kEventHandlerMap[] = {
{ "oncommand", nsnull, &NS_GET_IID(nsIDOMMenuListener) },
{ "onbroadcast", nsnull, &NS_GET_IID(nsIDOMMenuListener) },
{ "oncommandupdate", nsnull, &NS_GET_IID(nsIDOMMenuListener) },
{ "onoverflow", nsnull, &NS_GET_IID(nsIDOMMenuListener) },
{ "onunderflow", nsnull, &NS_GET_IID(nsIDOMMenuListener) },
{ "onfocus", nsnull, &NS_GET_IID(nsIDOMFocusListener) },
{ "onblur", nsnull, &NS_GET_IID(nsIDOMFocusListener) },

Просмотреть файл

@ -42,6 +42,8 @@ public:
NS_IMETHOD Action(nsIDOMEvent* aEvent) = 0;
NS_IMETHOD Broadcast(nsIDOMEvent* aEvent) = 0;
NS_IMETHOD CommandUpdate(nsIDOMEvent* aEvent) = 0;
NS_IMETHOD Overflow(nsIDOMEvent* aEvent) = 0;
NS_IMETHOD Underflow(nsIDOMEvent* aEvent) = 0;
};
#endif // nsIDOMMenuListener_h__

Просмотреть файл

@ -169,6 +169,9 @@ NS_NewGfxListControlFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
#endif
nsresult
NS_NewAutoRepeatBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame);
nsresult
NS_NewRootBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame);
@ -244,6 +247,9 @@ NS_NewMenuPopupFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
nsresult
NS_NewPopupSetFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
nsresult
NS_NewScrollBoxFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
nsresult
NS_NewMenuFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRUint32 aFlags );
@ -5513,7 +5519,7 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell,
// Create a frame based on the tag
// box is first because it is created the most.
// BOX CONSTRUCTION
if (aTag == nsXULAtoms::box || aTag == nsXULAtoms::tabbox ||
if (aTag == nsXULAtoms::box || aTag == nsXULAtoms::vbox || aTag == nsXULAtoms::hbox || aTag == nsXULAtoms::tabbox ||
aTag == nsXULAtoms::tabpage || aTag == nsXULAtoms::tabcontrol
#ifdef XULTREE
|| aTag == nsXULAtoms::treecell
@ -5527,7 +5533,10 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell,
rv = NS_NewXULTreeCellFrame(aPresShell, &newFrame);
else
#endif
rv = NS_NewBoxFrame(aPresShell, &newFrame);
// create a box. Its not root, its layout manager is default (nsnull) which is "sprocket" and
// its default orientation is horizontal for hbox and vertical for vbox
rv = NS_NewBoxFrame(aPresShell, &newFrame, PR_FALSE, nsnull, aTag != nsXULAtoms::vbox);
const nsStyleDisplay* display = (const nsStyleDisplay*)
aStyleContext->GetStyleData(eStyleStruct_Display);
@ -5574,8 +5583,33 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell,
}
} // End of BUTTON CONSTRUCTION logic
// BUTTON CONSTRUCTION
else if (aTag == nsXULAtoms::autorepeatbutton) {
processChildren = PR_TRUE;
isReplaced = PR_TRUE;
rv = NS_NewAutoRepeatBoxFrame(aPresShell, &newFrame);
// TITLED BUTTON CONSTRUCTION
const nsStyleDisplay* display = (const nsStyleDisplay*)
aStyleContext->GetStyleData(eStyleStruct_Display);
// Boxes can scroll.
if (IsScrollable(aPresContext, display)) {
// set the top to be the newly created scrollframe
BuildScrollFrame(aPresShell, aPresContext, aState, aContent, aStyleContext, newFrame, aParentFrame,
topFrame, aStyleContext);
// we have a scrollframe so the parent becomes the scroll frame.
newFrame->GetParent(&aParentFrame);
primaryFrameSet = PR_TRUE;
frameHasBeenInitialized = PR_TRUE;
}
} // End of BUTTON CONSTRUCTION logic
// TITLED BUTTON CONSTRUCTION
else if (aTag == nsXULAtoms::titledbutton) {
processChildren = PR_TRUE;
@ -5832,6 +5866,13 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell,
frameHasBeenInitialized = PR_TRUE;
}
}
else if (aTag == nsXULAtoms::scrollbox) {
rv = NS_NewScrollBoxFrame(aPresShell, &newFrame);
//ConstructTitledBoxFrame(aPresShell, aPresContext, aState, aContent, aParentFrame, aTag, aStyleContext, newFrame);
processChildren = PR_TRUE;
isReplaced = PR_TRUE;
}
else if (aTag == nsXULAtoms::spinner)
rv = NS_NewSpinnerFrame(aPresShell, &newFrame);

Просмотреть файл

@ -95,6 +95,12 @@ class nsIArena;
#define VERIFY_REFLOW_INCLUDE_SPACE_MANAGER 0x40
#define VERIFY_REFLOW_DURING_RESIZE_REFLOW 0x80
// for PostAttributeChanged
enum nsAttributeChangeType {
eChangeType_Set = 0, // Set attribute
eChangeType_Remove = 1, // Remove attribute
};
/**
* Presentation shell interface. Presentation shells are the
* controlling point for managing the presentation of a document. The
@ -251,6 +257,21 @@ public:
NS_IMETHOD FlushPendingNotifications() = 0;
/**
* Post a request to handle a DOM event after Reflow has finished.
*/
NS_IMETHOD PostDOMEvent(nsIContent* aContent, nsEvent* aEvent)=0;
/**
* Post a request to set and attribute after reflow has finished.
*/
NS_IMETHOD PostAttributeChange(nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aName,
const nsString& aValue,
PRBool aNotify,
nsAttributeChangeType aType) = 0;
/**
* Reflow batching
*/
NS_IMETHOD BeginReflowBatching() = 0;

Просмотреть файл

@ -159,6 +159,11 @@ LAYOUT_ATOM(onselect, "onselect")
LAYOUT_ATOM(onsubmit, "onsubmit")
LAYOUT_ATOM(onunload, "onunload")
// scrolling
LAYOUT_ATOM(onoverflow, "onoverflow")
LAYOUT_ATOM(onunderflow, "onunderflow")
#ifdef DEBUG
// Alphabetical list of atoms used by debugging code
LAYOUT_ATOM(cellMap, "TableCellMap")

Просмотреть файл

@ -553,6 +553,24 @@ private:
PRInt32 mCallCount;
};
struct nsDOMEventRequest
{
nsIContent* content;
nsEvent* event;
nsDOMEventRequest* next;
};
struct nsAttributeChangeRequest
{
nsIContent* content;
PRInt32 nameSpaceID;
nsIAtom* name;
nsAutoString value;
PRBool notify;
nsAttributeChangeType type;
nsAttributeChangeRequest* next;
};
class PresShell : public nsIPresShell, public nsIViewObserver,
private nsIDocumentObserver, public nsIFocusTracker,
public nsISelectionController,
@ -618,6 +636,20 @@ public:
NS_IMETHOD CancelReflowCommand(nsIFrame* aTargetFrame, nsIReflowCommand::ReflowType* aCmdType);
NS_IMETHOD FlushPendingNotifications();
/**
* Post a request to handle a DOM event after Reflow has finished.
*/
NS_IMETHOD PostDOMEvent(nsIContent* aContent, nsEvent* aEvent);
/**
* Post a request to set and attribute after reflow has finished.
*/
NS_IMETHOD PostAttributeChange(nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aName,
const nsString& aValue,
PRBool aNotify,
nsAttributeChangeType aType);
/**
* Reflow batching
*/
@ -753,6 +785,9 @@ public:
protected:
virtual ~PresShell();
void HandlePostedDOMEvents();
void HandlePostedAttributeChanges();
/** notify all external reflow observers that reflow of type "aData" is about
* to begin.
*/
@ -819,7 +854,14 @@ protected:
PRPackedBool mBatchReflows; // When set to true, the pres shell batches reflow commands.
nsCOMPtr<nsIObserverService> mObserverService; // Observer service for reflow events
nsCOMPtr<nsIDragService> mDragService;
// used for list of posted events and attribute changes. To be done
// after reflow.
nsDOMEventRequest* mFirstDOMEventRequest;
nsDOMEventRequest* mLastDOMEventRequest;
nsAttributeChangeRequest* mFirstAttributeRequest;
nsAttributeChangeRequest* mLastAttributeRequest;
// subshell map
nsDST* mSubShellMap; // map of content/subshell pairs
nsDST::NodeArena* mDSTNodeArena; // weak link. DST owns (mSubShellMap object)
@ -942,7 +984,11 @@ NS_NewPresShell(nsIPresShell** aInstancePtrResult)
(void **) aInstancePtrResult);
}
PresShell::PresShell():mStackArena(nsnull)
PresShell::PresShell():mStackArena(nsnull),
mFirstDOMEventRequest(nsnull),
mLastDOMEventRequest(nsnull),
mFirstAttributeRequest(nsnull),
mLastAttributeRequest(nsnull)
{
NS_INIT_REFCNT();
mIsDestroying = PR_FALSE;
@ -1828,6 +1874,8 @@ PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight)
#endif
mViewManager->CacheWidgetChanges(PR_FALSE);
HandlePostedDOMEvents();
HandlePostedAttributeChanges();
//Send resize event from here.
nsEvent event;
@ -3052,6 +3100,114 @@ PresShell::GetGeneratedContentIterator(nsIContent* aContent,
return rv;
}
/**
* Post a request to handle a DOM event after Reflow has finished.
* The event must have been created with the "new" operator.
*/
NS_IMETHODIMP
PresShell::PostDOMEvent(nsIContent* aContent, nsEvent* aEvent)
{
// ok we have a list of events to handle. Queue them up and handle them
// after we finish reflow.
nsDOMEventRequest* request = nsnull;
void* result = nsnull;
AllocateFrame(sizeof(nsDOMEventRequest), &result);
request = (nsDOMEventRequest*)result;
request->content = aContent;
NS_ADDREF(aContent);
request->event = aEvent;
request->next = nsnull;
if (mLastDOMEventRequest) {
mLastDOMEventRequest = mLastDOMEventRequest->next = request;
} else {
mFirstDOMEventRequest = request;
mLastDOMEventRequest = request;
}
return NS_OK;
}
/**
* Post a request to set and attribute after reflow has finished.
*/
NS_IMETHODIMP
PresShell::PostAttributeChange(nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aName,
const nsString& aValue,
PRBool aNotify,
nsAttributeChangeType aType)
{
// ok we have a list of events to handle. Queue them up and handle them
// after we finish reflow.
nsAttributeChangeRequest* request = nsnull;
void* result = nsnull;
AllocateFrame(sizeof(nsAttributeChangeRequest), &result);
request = (nsAttributeChangeRequest*)result;
request->content = aContent;
NS_ADDREF(aContent);
request->nameSpaceID = aNameSpaceID;
request->name = aName;
request->value = aValue;
request->notify = aNotify;
request->type = aType;
request->next = nsnull;
if (mLastAttributeRequest) {
mLastAttributeRequest = mLastAttributeRequest->next = request;
} else {
mFirstAttributeRequest = request;
mLastAttributeRequest = request;
}
return NS_OK;
}
void
PresShell::HandlePostedDOMEvents()
{
nsDOMEventRequest* node = mFirstDOMEventRequest;
while(node)
{
nsEventStatus status = nsEventStatus_eIgnore;
node->content->HandleDOMEvent(mPresContext, node->event, nsnull, NS_EVENT_FLAG_INIT, &status);
NS_RELEASE(node->content);
delete node->event;
nsDOMEventRequest* toFree = node;
node = node->next;
FreeFrame(sizeof(nsDOMEventRequest), toFree);
}
mFirstDOMEventRequest = mLastDOMEventRequest = nsnull;
}
void
PresShell::HandlePostedAttributeChanges()
{
nsAttributeChangeRequest* node = mFirstAttributeRequest;
while(node)
{
if (node->type == eChangeType_Set)
node->content->SetAttribute(node->nameSpaceID, node->name, node->value, node->notify);
else
node->content->UnsetAttribute(node->nameSpaceID, node->name, node->notify);
NS_RELEASE(node->content);
nsAttributeChangeRequest* toFree = node;
node = node->next;
FreeFrame(sizeof(nsAttributeChangeRequest), toFree);
}
mFirstAttributeRequest = mLastAttributeRequest = nsnull;
}
NS_IMETHODIMP
PresShell::FlushPendingNotifications()
{
@ -4001,8 +4157,8 @@ PresShell::ProcessReflowCommands(PRBool aInterruptible)
MOZ_TIMER_DEBUGLOG(("Stop: Reflow: PresShell::ProcessReflowCommands(), this=%p\n", this));
MOZ_TIMER_STOP(mReflowWatch);
// if we allocated any stack memory during reflow free it.
//FreeDynamicStack();
HandlePostedDOMEvents();
HandlePostedAttributeChanges();
return NS_OK;
}

Просмотреть файл

@ -95,6 +95,12 @@ class nsIArena;
#define VERIFY_REFLOW_INCLUDE_SPACE_MANAGER 0x40
#define VERIFY_REFLOW_DURING_RESIZE_REFLOW 0x80
// for PostAttributeChanged
enum nsAttributeChangeType {
eChangeType_Set = 0, // Set attribute
eChangeType_Remove = 1, // Remove attribute
};
/**
* Presentation shell interface. Presentation shells are the
* controlling point for managing the presentation of a document. The
@ -251,6 +257,21 @@ public:
NS_IMETHOD FlushPendingNotifications() = 0;
/**
* Post a request to handle a DOM event after Reflow has finished.
*/
NS_IMETHOD PostDOMEvent(nsIContent* aContent, nsEvent* aEvent)=0;
/**
* Post a request to set and attribute after reflow has finished.
*/
NS_IMETHOD PostAttributeChange(nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aName,
const nsString& aValue,
PRBool aNotify,
nsAttributeChangeType aType) = 0;
/**
* Reflow batching
*/
NS_IMETHOD BeginReflowBatching() = 0;

Просмотреть файл

@ -159,6 +159,11 @@ LAYOUT_ATOM(onselect, "onselect")
LAYOUT_ATOM(onsubmit, "onsubmit")
LAYOUT_ATOM(onunload, "onunload")
// scrolling
LAYOUT_ATOM(onoverflow, "onoverflow")
LAYOUT_ATOM(onunderflow, "onunderflow")
#ifdef DEBUG
// Alphabetical list of atoms used by debugging code
LAYOUT_ATOM(cellMap, "TableCellMap")

Просмотреть файл

@ -163,6 +163,10 @@
#define NS_TREEBOXOBJECT_CID \
{ 0x26621935, 0xf272, 0x4979, { 0x90, 0xa9, 0xe6, 0xed, 0x83, 0x56, 0x6c, 0x2e } }
// {56E2ADA8-4631-11d4-BA11-001083023C1E}
#define NS_SCROLLBOXOBJECT_CID \
{ 0x56e2ada8, 0x4631, 0x11d4, { 0xba, 0x11, 0x0, 0x10, 0x83, 0x2, 0x3c, 0x1e } }
// {AA40253B-4C42-4056-8132-37BCD07862FD}
#define NS_MENUBOXOBJECT_CID \
{ 0xaa40253b, 0x4c42, 0x4056, { 0x81, 0x32, 0x37, 0xbc, 0xd0, 0x78, 0x62, 0xfd } }

Просмотреть файл

@ -109,6 +109,7 @@ static NS_DEFINE_CID(kBindingManagerCID, NS_BINDINGMANAGER_CID);
static NS_DEFINE_CID(kBoxObjectCID, NS_BOXOBJECT_CID);
static NS_DEFINE_CID(kTreeBoxObjectCID, NS_TREEBOXOBJECT_CID);
static NS_DEFINE_CID(kScrollBoxObjectCID, NS_SCROLLBOXOBJECT_CID);
static NS_DEFINE_CID(kMenuBoxObjectCID, NS_MENUBOXOBJECT_CID);
static NS_DEFINE_CID(kPopupSetBoxObjectCID, NS_POPUPSETBOXOBJECT_CID);
static NS_DEFINE_CID(kBrowserBoxObjectCID, NS_BROWSERBOXOBJECT_CID);
@ -148,6 +149,7 @@ extern nsresult NS_NewBindingManager(nsIBindingManager** aResult);
extern nsresult NS_NewBoxObject(nsIBoxObject** aResult);
extern nsresult NS_NewTreeBoxObject(nsIBoxObject** aResult);
extern nsresult NS_NewScrollBoxObject(nsIBoxObject** aResult);
extern nsresult NS_NewMenuBoxObject(nsIBoxObject** aResult);
extern nsresult NS_NewEditorBoxObject(nsIBoxObject** aResult);
extern nsresult NS_NewPopupSetBoxObject(nsIBoxObject** aResult);
@ -515,6 +517,13 @@ nsLayoutFactory::CreateInstance(nsISupports *aOuter,
return res;
}
}
else if (mClassID.Equals(kScrollBoxObjectCID)) {
res = NS_NewScrollBoxObject((nsIBoxObject**) &inst);
if (NS_FAILED(res)) {
LOG_NEW_FAILURE("NS_NewScrollBoxObject", res);
return res;
}
}
else {
return NS_NOINTERFACE;
}

Просмотреть файл

@ -368,6 +368,7 @@ static Components gComponents[] = {
{ "XUL Browser Box Object", NS_BROWSERBOXOBJECT_CID, "component://netscape/layout/xul-boxobject-browser" },
{ "XUL Editor Box Object", NS_EDITORBOXOBJECT_CID, "component://netscape/layout/xul-boxobject-editor" },
{ "XUL Iframe Object", NS_IFRAMEBOXOBJECT_CID, "component://netscape/layout/xul-boxobject-iframe" },
{ "XUL ScrollBox Object", NS_SCROLLBOXOBJECT_CID, "component://netscape/layout/xul-boxobject-scrollbox" },
{ "AutoCopy Service", NS_AUTOCOPYSERVICE_CID, "component://netscape/autocopy" },
{ "Content policy service", NS_CONTENTPOLICY_CID, NS_CONTENTPOLICY_PROGID },

Просмотреть файл

@ -50,7 +50,7 @@ static char* mEventNames[] = {
"submit", "reset", "change", "select", "input", "paint" ,"text",
"create", "close", "destroy", "command", "broadcast", "commandupdate",
"dragenter", "dragover", "dragexit", "dragdrop", "draggesture", "resize",
"scroll"
"scroll","overflow", "underflow"
};
nsDOMEvent::nsDOMEvent(nsIPresContext* aPresContext, nsEvent* aEvent, const nsString& aEventType) {
@ -311,29 +311,48 @@ nsDOMEvent::GetDetail(PRInt32* aDetail)
{
//detail is valid for more than just mouseevents but we don't
//use it for anything else right now
if (!mEvent || mEvent->eventStructType != NS_MOUSE_EVENT) {
if (!mEvent) {
*aDetail = 0;
return NS_OK;
}
switch (mEvent->message) {
case NS_MOUSE_LEFT_BUTTON_UP:
case NS_MOUSE_LEFT_BUTTON_DOWN:
case NS_MOUSE_LEFT_CLICK:
case NS_MOUSE_LEFT_DOUBLECLICK:
case NS_MOUSE_MIDDLE_BUTTON_UP:
case NS_MOUSE_MIDDLE_BUTTON_DOWN:
case NS_MOUSE_MIDDLE_CLICK:
case NS_MOUSE_MIDDLE_DOUBLECLICK:
case NS_MOUSE_RIGHT_BUTTON_UP:
case NS_MOUSE_RIGHT_BUTTON_DOWN:
case NS_MOUSE_RIGHT_CLICK:
case NS_MOUSE_RIGHT_DOUBLECLICK:
*aDetail = ((nsMouseEvent*)mEvent)->clickCount;
break;
default:
break;
switch(mEvent->eventStructType)
{
case NS_SCROLLPORT_EVENT:
{
nsScrollPortEvent* scrollEvent = (nsScrollPortEvent*)mEvent;
*aDetail = (PRInt32)scrollEvent->orient;
return NS_OK;
}
case NS_MOUSE_EVENT:
{
switch (mEvent->message) {
case NS_MOUSE_LEFT_BUTTON_UP:
case NS_MOUSE_LEFT_BUTTON_DOWN:
case NS_MOUSE_LEFT_CLICK:
case NS_MOUSE_LEFT_DOUBLECLICK:
case NS_MOUSE_MIDDLE_BUTTON_UP:
case NS_MOUSE_MIDDLE_BUTTON_DOWN:
case NS_MOUSE_MIDDLE_CLICK:
case NS_MOUSE_MIDDLE_DOUBLECLICK:
case NS_MOUSE_RIGHT_BUTTON_UP:
case NS_MOUSE_RIGHT_BUTTON_DOWN:
case NS_MOUSE_RIGHT_CLICK:
case NS_MOUSE_RIGHT_DOUBLECLICK:
*aDetail = ((nsMouseEvent*)mEvent)->clickCount;
break;
default:
break;
}
}
default:
*aDetail = 0;
return NS_OK;
}
return NS_OK;
}
@ -1123,6 +1142,10 @@ const char* nsDOMEvent::GetEventName(PRUint32 aEventType)
return mEventNames[eDOMEvents_dragdrop];
case NS_DRAGDROP_GESTURE:
return mEventNames[eDOMEvents_draggesture];
case NS_SCROLLPORT_OVERFLOW:
return mEventNames[eDOMEvents_overflow];
case NS_SCROLLPORT_UNDERFLOW:
return mEventNames[eDOMEvents_underflow];
default:
break;
}

Просмотреть файл

@ -84,7 +84,9 @@ public:
eDOMEvents_dragdrop,
eDOMEvents_draggesture,
eDOMEvents_resize,
eDOMEvents_scroll
eDOMEvents_scroll,
eDOMEvents_overflow,
eDOMEvents_underflow
};
nsDOMEvent(nsIPresContext* aPresContext, nsEvent* aEvent, const nsString& aEventType);

Просмотреть файл

@ -450,6 +450,14 @@ nsresult nsEventListenerManager::GetIdentifiersForType(nsIAtom* aType, nsIID& aI
aIID = kIDOMMenuListenerIID;
*aFlags = NS_EVENT_BITS_XUL_COMMAND_UPDATE;
}
else if (aType == nsLayoutAtoms::onoverflow) {
aIID = kIDOMMenuListenerIID;
*aFlags = NS_EVENT_BITS_SCROLLPORT_OVERFLOW;
}
else if (aType == nsLayoutAtoms::onunderflow) {
aIID = kIDOMMenuListenerIID;
*aFlags = NS_EVENT_BITS_SCROLLPORT_UNDERFLOW;
}
else if (aType == nsLayoutAtoms::ondragenter) {
aIID = NS_GET_IID(nsIDOMDragListener);
*aFlags = NS_EVENT_BITS_DRAG_ENTER;
@ -1479,6 +1487,8 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext,
case NS_MENU_DESTROY:
case NS_MENU_ACTION:
case NS_XUL_BROADCAST:
case NS_SCROLLPORT_OVERFLOW:
case NS_SCROLLPORT_UNDERFLOW:
case NS_XUL_COMMAND_UPDATE:
if (nsnull != mMenuListeners) {
if (nsnull == *aDOMEvent) {
@ -1509,6 +1519,12 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext,
case NS_XUL_BROADCAST:
ret = mMenuListener->Broadcast(*aDOMEvent);
break;
case NS_SCROLLPORT_OVERFLOW:
ret = mMenuListener->Overflow(*aDOMEvent);
break;
case NS_SCROLLPORT_UNDERFLOW:
ret = mMenuListener->Underflow(*aDOMEvent);
break;
case NS_XUL_COMMAND_UPDATE:
ret = mMenuListener->CommandUpdate(*aDOMEvent);
break;
@ -1551,6 +1567,18 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext,
correctSubType = PR_TRUE;
}
break;
case NS_SCROLLPORT_OVERFLOW:
subType = NS_EVENT_BITS_SCROLLPORT_OVERFLOW;
if (ls->mSubType & NS_EVENT_BITS_SCROLLPORT_OVERFLOW) {
correctSubType = PR_TRUE;
}
break;
case NS_SCROLLPORT_UNDERFLOW:
subType = NS_EVENT_BITS_SCROLLPORT_UNDERFLOW;
if (ls->mSubType & NS_EVENT_BITS_SCROLLPORT_UNDERFLOW) {
correctSubType = PR_TRUE;
}
break;
case NS_XUL_COMMAND_UPDATE:
subType = NS_EVENT_BITS_XUL_COMMAND_UPDATE;
if (ls->mSubType & NS_EVENT_BITS_XUL_COMMAND_UPDATE) {

Просмотреть файл

@ -213,13 +213,15 @@ protected:
#define NS_EVENT_BITS_LOAD_ERROR 0x08
//nsIDOMMenuListener
#define NS_EVENT_BITS_MENU_NONE 0x00
#define NS_EVENT_BITS_MENU_CREATE 0x01
#define NS_EVENT_BITS_XUL_CLOSE 0x02
#define NS_EVENT_BITS_MENU_DESTROY 0x04
#define NS_EVENT_BITS_MENU_ACTION 0x08
#define NS_EVENT_BITS_XUL_BROADCAST 0x10
#define NS_EVENT_BITS_XUL_COMMAND_UPDATE 0x20
#define NS_EVENT_BITS_MENU_NONE 0x00
#define NS_EVENT_BITS_MENU_CREATE 0x01
#define NS_EVENT_BITS_XUL_CLOSE 0x02
#define NS_EVENT_BITS_MENU_DESTROY 0x04
#define NS_EVENT_BITS_MENU_ACTION 0x08
#define NS_EVENT_BITS_XUL_BROADCAST 0x10
#define NS_EVENT_BITS_XUL_COMMAND_UPDATE 0x20
#define NS_EVENT_BITS_SCROLLPORT_OVERFLOW 0x40
#define NS_EVENT_BITS_SCROLLPORT_UNDERFLOW 0x80
//nsIDOMDragListener
#define NS_EVENT_BITS_DRAG_NONE 0x00

Просмотреть файл

@ -553,6 +553,24 @@ private:
PRInt32 mCallCount;
};
struct nsDOMEventRequest
{
nsIContent* content;
nsEvent* event;
nsDOMEventRequest* next;
};
struct nsAttributeChangeRequest
{
nsIContent* content;
PRInt32 nameSpaceID;
nsIAtom* name;
nsAutoString value;
PRBool notify;
nsAttributeChangeType type;
nsAttributeChangeRequest* next;
};
class PresShell : public nsIPresShell, public nsIViewObserver,
private nsIDocumentObserver, public nsIFocusTracker,
public nsISelectionController,
@ -618,6 +636,20 @@ public:
NS_IMETHOD CancelReflowCommand(nsIFrame* aTargetFrame, nsIReflowCommand::ReflowType* aCmdType);
NS_IMETHOD FlushPendingNotifications();
/**
* Post a request to handle a DOM event after Reflow has finished.
*/
NS_IMETHOD PostDOMEvent(nsIContent* aContent, nsEvent* aEvent);
/**
* Post a request to set and attribute after reflow has finished.
*/
NS_IMETHOD PostAttributeChange(nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aName,
const nsString& aValue,
PRBool aNotify,
nsAttributeChangeType aType);
/**
* Reflow batching
*/
@ -753,6 +785,9 @@ public:
protected:
virtual ~PresShell();
void HandlePostedDOMEvents();
void HandlePostedAttributeChanges();
/** notify all external reflow observers that reflow of type "aData" is about
* to begin.
*/
@ -819,7 +854,14 @@ protected:
PRPackedBool mBatchReflows; // When set to true, the pres shell batches reflow commands.
nsCOMPtr<nsIObserverService> mObserverService; // Observer service for reflow events
nsCOMPtr<nsIDragService> mDragService;
// used for list of posted events and attribute changes. To be done
// after reflow.
nsDOMEventRequest* mFirstDOMEventRequest;
nsDOMEventRequest* mLastDOMEventRequest;
nsAttributeChangeRequest* mFirstAttributeRequest;
nsAttributeChangeRequest* mLastAttributeRequest;
// subshell map
nsDST* mSubShellMap; // map of content/subshell pairs
nsDST::NodeArena* mDSTNodeArena; // weak link. DST owns (mSubShellMap object)
@ -942,7 +984,11 @@ NS_NewPresShell(nsIPresShell** aInstancePtrResult)
(void **) aInstancePtrResult);
}
PresShell::PresShell():mStackArena(nsnull)
PresShell::PresShell():mStackArena(nsnull),
mFirstDOMEventRequest(nsnull),
mLastDOMEventRequest(nsnull),
mFirstAttributeRequest(nsnull),
mLastAttributeRequest(nsnull)
{
NS_INIT_REFCNT();
mIsDestroying = PR_FALSE;
@ -1828,6 +1874,8 @@ PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight)
#endif
mViewManager->CacheWidgetChanges(PR_FALSE);
HandlePostedDOMEvents();
HandlePostedAttributeChanges();
//Send resize event from here.
nsEvent event;
@ -3052,6 +3100,114 @@ PresShell::GetGeneratedContentIterator(nsIContent* aContent,
return rv;
}
/**
* Post a request to handle a DOM event after Reflow has finished.
* The event must have been created with the "new" operator.
*/
NS_IMETHODIMP
PresShell::PostDOMEvent(nsIContent* aContent, nsEvent* aEvent)
{
// ok we have a list of events to handle. Queue them up and handle them
// after we finish reflow.
nsDOMEventRequest* request = nsnull;
void* result = nsnull;
AllocateFrame(sizeof(nsDOMEventRequest), &result);
request = (nsDOMEventRequest*)result;
request->content = aContent;
NS_ADDREF(aContent);
request->event = aEvent;
request->next = nsnull;
if (mLastDOMEventRequest) {
mLastDOMEventRequest = mLastDOMEventRequest->next = request;
} else {
mFirstDOMEventRequest = request;
mLastDOMEventRequest = request;
}
return NS_OK;
}
/**
* Post a request to set and attribute after reflow has finished.
*/
NS_IMETHODIMP
PresShell::PostAttributeChange(nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aName,
const nsString& aValue,
PRBool aNotify,
nsAttributeChangeType aType)
{
// ok we have a list of events to handle. Queue them up and handle them
// after we finish reflow.
nsAttributeChangeRequest* request = nsnull;
void* result = nsnull;
AllocateFrame(sizeof(nsAttributeChangeRequest), &result);
request = (nsAttributeChangeRequest*)result;
request->content = aContent;
NS_ADDREF(aContent);
request->nameSpaceID = aNameSpaceID;
request->name = aName;
request->value = aValue;
request->notify = aNotify;
request->type = aType;
request->next = nsnull;
if (mLastAttributeRequest) {
mLastAttributeRequest = mLastAttributeRequest->next = request;
} else {
mFirstAttributeRequest = request;
mLastAttributeRequest = request;
}
return NS_OK;
}
void
PresShell::HandlePostedDOMEvents()
{
nsDOMEventRequest* node = mFirstDOMEventRequest;
while(node)
{
nsEventStatus status = nsEventStatus_eIgnore;
node->content->HandleDOMEvent(mPresContext, node->event, nsnull, NS_EVENT_FLAG_INIT, &status);
NS_RELEASE(node->content);
delete node->event;
nsDOMEventRequest* toFree = node;
node = node->next;
FreeFrame(sizeof(nsDOMEventRequest), toFree);
}
mFirstDOMEventRequest = mLastDOMEventRequest = nsnull;
}
void
PresShell::HandlePostedAttributeChanges()
{
nsAttributeChangeRequest* node = mFirstAttributeRequest;
while(node)
{
if (node->type == eChangeType_Set)
node->content->SetAttribute(node->nameSpaceID, node->name, node->value, node->notify);
else
node->content->UnsetAttribute(node->nameSpaceID, node->name, node->notify);
NS_RELEASE(node->content);
nsAttributeChangeRequest* toFree = node;
node = node->next;
FreeFrame(sizeof(nsAttributeChangeRequest), toFree);
}
mFirstAttributeRequest = mLastAttributeRequest = nsnull;
}
NS_IMETHODIMP
PresShell::FlushPendingNotifications()
{
@ -4001,8 +4157,8 @@ PresShell::ProcessReflowCommands(PRBool aInterruptible)
MOZ_TIMER_DEBUGLOG(("Stop: Reflow: PresShell::ProcessReflowCommands(), this=%p\n", this));
MOZ_TIMER_STOP(mReflowWatch);
// if we allocated any stack memory during reflow free it.
//FreeDynamicStack();
HandlePostedDOMEvents();
HandlePostedAttributeChanges();
return NS_OK;
}

Просмотреть файл

@ -17,57 +17,17 @@
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Author: Eric D Vaughan (evaughan@netscape.com)
*
* Contributor(s):
* Pierre Phaneuf <pp@ludusdesign.com>
*/
#include "nsCOMPtr.h"
#include "nsHTMLParts.h"
#include "nsIPresContext.h"
#include "nsIStyleContext.h"
#include "nsIReflowCommand.h"
#include "nsIDeviceContext.h"
#include "nsPageFrame.h"
#include "nsViewsCID.h"
#include "nsIView.h"
#include "nsIViewManager.h"
#include "nsHTMLContainerFrame.h"
#include "nsHTMLIIDs.h"
#include "nsCSSRendering.h"
#include "nsIScrollableView.h"
#include "nsWidgetsCID.h"
#include "nsScrollPortFrame.h"
#include "nsLayoutAtoms.h"
#include "nsIBox.h"
#include "nsBoxLayoutState.h"
#include "nsIBoxToBlockAdaptor.h"
#include "nsIFormControlFrame.h"
#include "nsIStatefulFrame.h"
#include "nsISupportsPrimitives.h"
#include "nsIPresState.h"
/*
static NS_DEFINE_IID(kWidgetCID, NS_CHILD_CID);
static NS_DEFINE_IID(kScrollingViewCID, NS_SCROLLING_VIEW_CID);
static NS_DEFINE_IID(kViewCID, NS_VIEW_CID);
static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID);
static NS_DEFINE_IID(kScrollViewIID, NS_ISCROLLABLEVIEW_IID);
static NS_DEFINE_IID(kAreaFrameIID, NS_IAREAFRAME_IID);
*/
static NS_DEFINE_IID(kWidgetCID, NS_CHILD_CID);
static NS_DEFINE_IID(kScrollPortViewCID, NS_SCROLL_PORT_VIEW_CID);
static NS_DEFINE_IID(kViewCID, NS_VIEW_CID);
static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID);
static NS_DEFINE_IID(kScrollViewIID, NS_ISCROLLABLEVIEW_IID);
static NS_DEFINE_IID(kIFormControlFrameIID, NS_IFORMCONTROLFRAME_IID);
//----------------------------------------------------------------------
nsresult
NS_NewScrollPortFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
{
@ -83,114 +43,8 @@ NS_NewScrollPortFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
return NS_OK;
}
nsScrollPortFrame::nsScrollPortFrame(nsIPresShell* aShell):nsBoxFrame(aShell)
{
}
NS_IMETHODIMP
nsScrollPortFrame::Init(nsIPresContext* aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aStyleContext,
nsIFrame* aPrevInFlow)
{
nsresult rv = nsBoxFrame::Init(aPresContext, aContent,
aParent, aStyleContext,
aPrevInFlow);
// Create the scrolling view
CreateScrollingView(aPresContext);
return rv;
}
NS_IMETHODIMP
nsScrollPortFrame::SetInitialChildList(nsIPresContext* aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList)
{
nsresult rv = nsBoxFrame::SetInitialChildList(aPresContext, aListName,
aChildList);
nsIFrame* frame = mFrames.FirstChild();
// There must be one and only one child frame
if (!frame) {
return NS_ERROR_INVALID_ARG;
} else if (mFrames.GetLength() > 1) {
return NS_ERROR_UNEXPECTED;
}
#ifdef NS_DEBUG
// Verify that the scrolled frame has a view
nsIView* scrolledView;
frame->GetView(aPresContext, &scrolledView);
NS_ASSERTION(nsnull != scrolledView, "no view");
#endif
// We need to allow the view's position to be different than the
// frame's position
nsFrameState state;
frame->GetFrameState(&state);
state &= ~NS_FRAME_SYNC_FRAME_AND_VIEW;
frame->SetFrameState(state);
return rv;
}
NS_IMETHODIMP
nsScrollPortFrame::AppendFrames(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aFrameList)
{
// Only one child frame allowed
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsScrollPortFrame::InsertFrames(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aPrevFrame,
nsIFrame* aFrameList)
{
// Only one child frame allowed
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsScrollPortFrame::RemoveFrame(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aOldFrame)
{
// Scroll frame doesn't support incremental changes
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult
nsScrollPortFrame::CreateScrollingViewWidget(nsIView* aView, const nsStylePosition* aPosition)
{
nsresult rv = NS_OK;
// If it's fixed positioned, then create a widget
if (NS_STYLE_POSITION_FIXED == aPosition->mPosition) {
rv = aView->CreateWidget(kWidgetCID);
}
return(rv);
}
nsresult
nsScrollPortFrame::GetScrollingParentView(nsIPresContext* aPresContext,
nsIFrame* aParent,
nsIView** aParentView)
{
nsresult rv = aParent->GetView(aPresContext, aParentView);
NS_ASSERTION(aParentView, "GetParentWithView failed");
return(rv);
}
PRBool
nsScrollPortFrame::IsInsideFormControlFrame()
nsScrollPortFrame::NeedsClipWidget()
{
// XXX: This code will go away when a general solution for creating
// widgets only when needed is implemented.
@ -208,444 +62,14 @@ nsScrollPortFrame::IsInsideFormControlFrame()
return PR_FALSE;
}
nsresult
nsScrollPortFrame::CreateScrollingView(nsIPresContext* aPresContext)
{
nsIView* view;
//Get parent frame
nsIFrame* parent;
GetParentWithView(aPresContext, &parent);
NS_ASSERTION(parent, "GetParentWithView failed");
// Get parent view
nsIView* parentView = nsnull;
GetScrollingParentView(aPresContext, parent, &parentView);
// Get the view manager
nsIViewManager* viewManager;
parentView->GetViewManager(viewManager);
// Create the scrolling view
nsresult rv = nsComponentManager::CreateInstance(kScrollPortViewCID,
nsnull,
kIViewIID,
(void **)&view);
if (NS_OK == rv) {
const nsStylePosition* position = (const nsStylePosition*)
mStyleContext->GetStyleData(eStyleStruct_Position);
const nsStyleColor* color = (const nsStyleColor*)
mStyleContext->GetStyleData(eStyleStruct_Color);
const nsStyleSpacing* spacing = (const nsStyleSpacing*)
mStyleContext->GetStyleData(eStyleStruct_Spacing);
const nsStyleDisplay* display = (const nsStyleDisplay*)
mStyleContext->GetStyleData(eStyleStruct_Display);
// Get the z-index
PRInt32 zIndex = 0;
if (eStyleUnit_Integer == position->mZIndex.GetUnit()) {
zIndex = position->mZIndex.GetIntValue();
}
// Initialize the scrolling view
view->Init(viewManager, mRect, parentView, display->IsVisibleOrCollapsed() ?
nsViewVisibility_kShow : nsViewVisibility_kHide);
// Insert the view into the view hierarchy
viewManager->InsertChild(parentView, view, zIndex);
// Set the view's opacity
viewManager->SetViewOpacity(view, color->mOpacity);
// Because we only paint the border and we don't paint a background,
// inform the view manager that we have transparent content
viewManager->SetViewContentTransparency(view, PR_TRUE);
// If it's fixed positioned, then create a widget too
CreateScrollingViewWidget(view, position);
// Get the nsIScrollableView interface
nsIScrollableView* scrollingView;
view->QueryInterface(kScrollViewIID, (void**)&scrollingView);
scrollingView->SetScrollPreference(nsScrollPreference_kNeverScroll);
// Have the scrolling view create its internal widgets
if (! IsInsideFormControlFrame()) {
scrollingView->CreateScrollControls();
}
// Set the scrolling view's insets to whatever our border is
nsMargin border;
if (!spacing->GetBorder(border)) {
NS_NOTYETIMPLEMENTED("percentage border");
border.SizeTo(0, 0, 0, 0);
}
scrollingView->SetControlInsets(border);
// Remember our view
SetView(aPresContext, view);
}
NS_RELEASE(viewManager);
return rv;
}
NS_IMETHODIMP
nsScrollPortFrame::GetMargin(nsMargin& aMargin)
{
aMargin.SizeTo(0,0,0,0);
return NS_OK;
}
NS_IMETHODIMP
nsScrollPortFrame::GetPadding(nsMargin& aMargin)
{
aMargin.SizeTo(0,0,0,0);
return NS_OK;
}
NS_IMETHODIMP
nsScrollPortFrame::GetBorder(nsMargin& aMargin)
{
aMargin.SizeTo(0,0,0,0);
return NS_OK;
}
NS_IMETHODIMP
nsScrollPortFrame::Layout(nsBoxLayoutState& aState)
{
PRUint32 flags = 0;
aState.GetLayoutFlags(flags);
nsRect clientRect(0,0,0,0);
GetClientRect(clientRect);
nsIBox* kid = nsnull;
GetChildBox(&kid);
nsRect childRect(clientRect);
nsMargin margin(0,0,0,0);
kid->GetMargin(margin);
childRect.Deflate(margin);
nsSize min(0,0);
kid->GetMinSize(aState, min);
/*
// if our child is not html then get is min size
// and make sure we don't squeeze it smaller than that.
nsIBoxToBlockAdaptor* adaptor = nsnull;
if (NS_FAILED(kid->QueryInterface(NS_GET_IID(nsIBoxToBlockAdaptor), (void**)&adaptor))) {
if (min.height > childRect.height)
childRect.height = min.height;
}
*/
if (min.height > childRect.height)
childRect.height = min.height;
if (min.width > childRect.width)
childRect.width = min.width;
aState.SetLayoutFlags(NS_FRAME_NO_MOVE_VIEW);
kid->SetBounds(aState, childRect);
kid->Layout(aState);
kid->GetBounds(childRect);
clientRect.Inflate(margin);
if (childRect.width < clientRect.width || childRect.height < childRect.height)
{
if (childRect.width < clientRect.width)
childRect.width = clientRect.width;
if (childRect.height < clientRect.height)
childRect.height = clientRect.height;
clientRect.Deflate(margin);
kid->SetBounds(aState, childRect);
}
aState.SetLayoutFlags(flags);
SyncLayout(aState);
nsIPresContext* presContext = aState.GetPresContext();
nsIScrollableView* scrollingView;
nsIView* view;
GetView(presContext, &view);
if (NS_SUCCEEDED(view->QueryInterface(kScrollViewIID, (void**)&scrollingView))) {
scrollingView->ComputeScrollOffsets(PR_TRUE);
}
return NS_OK;
}
NS_IMETHODIMP
nsScrollPortFrame::GetAscent(nsBoxLayoutState& aState, nscoord& aAscent)
{
aAscent = 0;
nsIBox* child = nsnull;
GetChildBox(&child);
nsresult rv = child->GetAscent(aState, aAscent);
nsMargin m(0,0,0,0);
GetBorderAndPadding(m);
aAscent += m.top;
GetMargin(m);
aAscent += m.top;
GetInset(m);
aAscent += m.top;
return rv;
}
NS_IMETHODIMP
nsScrollPortFrame::GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize)
{
nsIBox* child = nsnull;
GetChildBox(&child);
nsresult rv = child->GetPrefSize(aBoxLayoutState, aSize);
AddMargin(child, aSize);
AddBorderAndPadding(aSize);
AddInset(aSize);
nsIBox::AddCSSPrefSize(aBoxLayoutState, this, aSize);
return rv;
}
NS_IMETHODIMP
nsScrollPortFrame::GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize)
{
aSize.width = 0;
aSize.height = 0;
AddBorderAndPadding(aSize);
AddInset(aSize);
nsIBox::AddCSSMinSize(aBoxLayoutState, this, aSize);
return NS_OK;
}
NS_IMETHODIMP
nsScrollPortFrame::GetMaxSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize)
{
nsIBox* child = nsnull;
GetChildBox(&child);
nsresult rv = child->GetMaxSize(aBoxLayoutState, aSize);
AddMargin(child, aSize);
AddBorderAndPadding(aSize);
AddInset(aSize);
nsIBox::AddCSSMaxSize(aBoxLayoutState, this, aSize);
return rv;
}
NS_IMETHODIMP
nsScrollPortFrame::Paint(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer)
{
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
// Only paint the border and background if we're visible
const nsStyleDisplay* display = (const nsStyleDisplay*)
mStyleContext->GetStyleData(eStyleStruct_Display);
if (display->IsVisibleOrCollapsed()) {
// Paint our border only (no background)
const nsStyleSpacing* spacing = (const nsStyleSpacing*)
mStyleContext->GetStyleData(eStyleStruct_Spacing);
nsRect rect(0, 0, mRect.width, mRect.height);
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *spacing, mStyleContext, 0);
}
}
// Paint our children
nsresult rv = nsBoxFrame::Paint(aPresContext, aRenderingContext, aDirtyRect,
aWhichLayer);
return rv;
}
PRIntn
nsScrollPortFrame::GetSkipSides() const
{
return 0;
}
nsresult
nsScrollPortFrame::GetContentOf(nsIContent** aContent)
{
return GetContent(aContent);
}
//----------------------------------------------------------------------
// nsIStatefulFrame
//----------------------------------------------------------------------
NS_IMETHODIMP
nsScrollPortFrame::GetStateType(nsIPresContext* aPresContext,
nsIStatefulFrame::StateType* aStateType)
{
*aStateType = nsIStatefulFrame::eScrollType;
return NS_OK;
}
//----------------------------------------------------------------------
NS_IMETHODIMP
nsScrollPortFrame::SaveState(nsIPresContext* aPresContext,
nsIPresState** aState)
{
nsresult res = NS_OK;
PRInt32 x,y;
nsIScrollableView* scrollingView;
nsIView* view;
GetView(aPresContext, &view);
if (NS_SUCCEEDED(view->QueryInterface(kScrollViewIID, (void**)&scrollingView))) {
scrollingView->GetScrollPosition(x,y);
}
nsIView* child = nsnull;
nsRect childRect(0,0,0,0);
if (NS_SUCCEEDED(scrollingView->GetScrolledView(child)) && child) {
child->GetBounds(childRect);
}
res = NS_NewPresState(aState);
nsCOMPtr<nsISupportsPRInt32> xoffset;
if (NS_SUCCEEDED(res)) {
res = nsComponentManager::CreateInstance(NS_SUPPORTS_PRINT32_PROGID,
nsnull, NS_GET_IID(nsISupportsPRInt32), (void**)getter_AddRefs(xoffset));
if (NS_SUCCEEDED(res) && xoffset) {
res = xoffset->SetData(x);
if (NS_SUCCEEDED(res)) {
(*aState)->SetStatePropertyAsSupports(NS_ConvertASCIItoUCS2("x-offset"), xoffset);
}
}
}
nsCOMPtr<nsISupportsPRInt32> yoffset;
if (NS_SUCCEEDED(res)) {
res = nsComponentManager::CreateInstance(NS_SUPPORTS_PRINT32_PROGID,
nsnull, NS_GET_IID(nsISupportsPRInt32), (void**)getter_AddRefs(yoffset));
if (NS_SUCCEEDED(res) && yoffset) {
res = yoffset->SetData(y);
if (NS_SUCCEEDED(res)) {
(*aState)->SetStatePropertyAsSupports(NS_ConvertASCIItoUCS2("y-offset"), yoffset);
}
}
}
nsCOMPtr<nsISupportsPRInt32> width;
if (NS_SUCCEEDED(res)) {
res = nsComponentManager::CreateInstance(NS_SUPPORTS_PRINT32_PROGID,
nsnull, NS_GET_IID(nsISupportsPRInt32), (void**)getter_AddRefs(width));
if (NS_SUCCEEDED(res) && width) {
res = width->SetData(childRect.width);
if (NS_SUCCEEDED(res)) {
(*aState)->SetStatePropertyAsSupports(NS_ConvertASCIItoUCS2("width"), width);
}
}
}
nsCOMPtr<nsISupportsPRInt32> height;
if (NS_SUCCEEDED(res)) {
res = nsComponentManager::CreateInstance(NS_SUPPORTS_PRINT32_PROGID,
nsnull, NS_GET_IID(nsISupportsPRInt32), (void**)getter_AddRefs(height));
if (NS_SUCCEEDED(res) && height) {
res = height->SetData(childRect.height);
if (NS_SUCCEEDED(res)) {
(*aState)->SetStatePropertyAsSupports(NS_ConvertASCIItoUCS2("height"), height);
}
}
}
return res;
}
//-----------------------------------------------------------
NS_IMETHODIMP
nsScrollPortFrame::RestoreState(nsIPresContext* aPresContext,
nsIPresState* aState)
{
nsCOMPtr<nsISupportsPRInt32> xoffset;
nsCOMPtr<nsISupportsPRInt32> yoffset;
nsCOMPtr<nsISupportsPRInt32> width;
nsCOMPtr<nsISupportsPRInt32> height;
aState->GetStatePropertyAsSupports(NS_ConvertASCIItoUCS2("x-offset"), getter_AddRefs(xoffset));
aState->GetStatePropertyAsSupports(NS_ConvertASCIItoUCS2("y-offset"), getter_AddRefs(yoffset));
aState->GetStatePropertyAsSupports(NS_ConvertASCIItoUCS2("width"), getter_AddRefs(width));
aState->GetStatePropertyAsSupports(NS_ConvertASCIItoUCS2("height"), getter_AddRefs(height));
nsresult res = NS_ERROR_NULL_POINTER;
if (xoffset && yoffset) {
PRInt32 x,y,w,h;
res = xoffset->GetData(&x);
if (NS_SUCCEEDED(res))
res = yoffset->GetData(&y);
if (NS_SUCCEEDED(res))
res = width->GetData(&w);
if (NS_SUCCEEDED(res))
res = height->GetData(&h);
if (NS_SUCCEEDED(res)) {
nsIScrollableView* scrollingView;
nsIView* view;
GetView(aPresContext, &view);
if (NS_SUCCEEDED(view->QueryInterface(kScrollViewIID, (void**)&scrollingView))) {
nsIView* child = nsnull;
nsRect childRect(0,0,0,0);
if (NS_SUCCEEDED(scrollingView->GetScrolledView(child)) && child) {
child->GetBounds(childRect);
}
x = (int)(((float)childRect.width / w) * x);
y = (int)(((float)childRect.height / h) * y);
scrollingView->ScrollTo(x,y,0);
}
}
}
return res;
}
NS_IMETHODIMP
nsScrollPortFrame::GetFrameType(nsIAtom** aType) const
{
NS_PRECONDITION(nsnull != aType, "null OUT parameter pointer");
*aType = nsLayoutAtoms::scrollFrame;
NS_ADDREF(*aType);
return NS_OK;
}
#ifdef NS_DEBUG
NS_IMETHODIMP
nsScrollPortFrame::GetFrameName(nsString& aResult) const
{
return MakeFrameName("ScrollPort", aResult);
return MakeFrameName("ScrollPortFrame", aResult);
}
#endif
NS_IMETHODIMP_(nsrefcnt)
nsScrollPortFrame::AddRef(void)
nsScrollPortFrame::nsScrollPortFrame(nsIPresShell* aShell):nsScrollBoxFrame(aShell)
{
return NS_OK;
}
NS_IMETHODIMP_(nsrefcnt)
nsScrollPortFrame::Release(void)
{
return NS_OK;
}
NS_INTERFACE_MAP_BEGIN(nsScrollPortFrame)
NS_INTERFACE_MAP_ENTRY(nsIBox)
NS_INTERFACE_MAP_ENTRY(nsIStatefulFrame)
#ifdef NS_DEBUG
NS_INTERFACE_MAP_ENTRY(nsIFrameDebug)
#endif
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIBox)
NS_INTERFACE_MAP_END_INHERITING(nsBoxFrame)

Просмотреть файл

@ -22,108 +22,28 @@
#ifndef nsScrollPortFrame_h___
#define nsScrollPortFrame_h___
#include "nsBoxFrame.h"
#include "nsIStatefulFrame.h"
#include "nsScrollBoxFrame.h"
/**
* The scroll frame creates and manages the scrolling view
*
* It only supports having a single child frame that typically is an area
* frame, but doesn't have to be. The child frame must have a view, though
* This is a specialized subclass for HTML only.
*
* Scroll frames don't support incremental changes, i.e. you can't replace
* or remove the scrolled frame
*/
class nsScrollPortFrame : nsBoxFrame,
public nsIStatefulFrame {
class nsScrollPortFrame : public nsScrollBoxFrame {
public:
friend nsresult NS_NewScrollPortFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
NS_IMETHOD Init(nsIPresContext* aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow);
// Called to set the one and only child frame. Returns NS_ERROR_INVALID_ARG
// if the child frame is NULL, and NS_ERROR_UNEXPECTED if the child list
// contains more than one frame
NS_IMETHOD SetInitialChildList(nsIPresContext* aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList);
// Because there can be only one child frame, these two function return
// NS_ERROR_FAILURE
NS_IMETHOD AppendFrames(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aFrameList);
NS_IMETHOD InsertFrames(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aPrevFrame,
nsIFrame* aFrameList);
// This function returns NS_ERROR_NOT_IMPLEMENTED
NS_IMETHOD RemoveFrame(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aOldFrame);
NS_IMETHOD Paint(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer);
/**
* Get the "type" of the frame
*
* @see nsLayoutAtoms::scrollFrame
*/
NS_IMETHOD GetFrameType(nsIAtom** aType) const;
#ifdef NS_DEBUG
NS_IMETHOD GetFrameName(nsString& aResult) const;
NS_IMETHOD GetFrameName(nsString& aResult) const;
#endif
// nsIBox methods
NS_DECL_ISUPPORTS
NS_IMETHOD GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize);
NS_IMETHOD GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize);
NS_IMETHOD GetMaxSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize);
NS_IMETHOD GetAscent(nsBoxLayoutState& aBoxLayoutState, nscoord& aAscent);
NS_IMETHOD Layout(nsBoxLayoutState& aBoxLayoutState);
NS_IMETHOD GetPadding(nsMargin& aMargin);
NS_IMETHOD GetBorder(nsMargin& aMargin);
NS_IMETHOD GetMargin(nsMargin& aMargin);
virtual nsresult GetContentOf(nsIContent** aContent);
//nsIStatefulFrame
NS_IMETHOD GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType);
NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState);
NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState);
protected:
nsScrollPortFrame(nsIPresShell* aShell);
virtual PRIntn GetSkipSides() const;
// Creation of the widget for the scrolling view is factored into a virtual method so
// that sub-classes may control widget creation.
virtual nsresult CreateScrollingViewWidget(nsIView* aView,const nsStylePosition* aPosition);
// Getting the view for scollframe may be overriden to provide a parent view for te scroll frame
virtual nsresult GetScrollingParentView(nsIPresContext* aPresContext,
nsIFrame* aParent,
nsIView** aParentView);
private:
nsresult CreateScrollingView(nsIPresContext* aPresContext);
PRBool IsInsideFormControlFrame();
virtual PRBool NeedsClipWidget();
};
#endif /* nsScrollPortFrame_h___ */

Просмотреть файл

@ -169,6 +169,9 @@ NS_NewGfxListControlFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
#endif
nsresult
NS_NewAutoRepeatBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame);
nsresult
NS_NewRootBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame);
@ -244,6 +247,9 @@ NS_NewMenuPopupFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
nsresult
NS_NewPopupSetFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
nsresult
NS_NewScrollBoxFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
nsresult
NS_NewMenuFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRUint32 aFlags );
@ -5513,7 +5519,7 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell,
// Create a frame based on the tag
// box is first because it is created the most.
// BOX CONSTRUCTION
if (aTag == nsXULAtoms::box || aTag == nsXULAtoms::tabbox ||
if (aTag == nsXULAtoms::box || aTag == nsXULAtoms::vbox || aTag == nsXULAtoms::hbox || aTag == nsXULAtoms::tabbox ||
aTag == nsXULAtoms::tabpage || aTag == nsXULAtoms::tabcontrol
#ifdef XULTREE
|| aTag == nsXULAtoms::treecell
@ -5527,7 +5533,10 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell,
rv = NS_NewXULTreeCellFrame(aPresShell, &newFrame);
else
#endif
rv = NS_NewBoxFrame(aPresShell, &newFrame);
// create a box. Its not root, its layout manager is default (nsnull) which is "sprocket" and
// its default orientation is horizontal for hbox and vertical for vbox
rv = NS_NewBoxFrame(aPresShell, &newFrame, PR_FALSE, nsnull, aTag != nsXULAtoms::vbox);
const nsStyleDisplay* display = (const nsStyleDisplay*)
aStyleContext->GetStyleData(eStyleStruct_Display);
@ -5574,8 +5583,33 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell,
}
} // End of BUTTON CONSTRUCTION logic
// BUTTON CONSTRUCTION
else if (aTag == nsXULAtoms::autorepeatbutton) {
processChildren = PR_TRUE;
isReplaced = PR_TRUE;
rv = NS_NewAutoRepeatBoxFrame(aPresShell, &newFrame);
// TITLED BUTTON CONSTRUCTION
const nsStyleDisplay* display = (const nsStyleDisplay*)
aStyleContext->GetStyleData(eStyleStruct_Display);
// Boxes can scroll.
if (IsScrollable(aPresContext, display)) {
// set the top to be the newly created scrollframe
BuildScrollFrame(aPresShell, aPresContext, aState, aContent, aStyleContext, newFrame, aParentFrame,
topFrame, aStyleContext);
// we have a scrollframe so the parent becomes the scroll frame.
newFrame->GetParent(&aParentFrame);
primaryFrameSet = PR_TRUE;
frameHasBeenInitialized = PR_TRUE;
}
} // End of BUTTON CONSTRUCTION logic
// TITLED BUTTON CONSTRUCTION
else if (aTag == nsXULAtoms::titledbutton) {
processChildren = PR_TRUE;
@ -5832,6 +5866,13 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell,
frameHasBeenInitialized = PR_TRUE;
}
}
else if (aTag == nsXULAtoms::scrollbox) {
rv = NS_NewScrollBoxFrame(aPresShell, &newFrame);
//ConstructTitledBoxFrame(aPresShell, aPresContext, aState, aContent, aParentFrame, aTag, aStyleContext, newFrame);
processChildren = PR_TRUE;
isReplaced = PR_TRUE;
}
else if (aTag == nsXULAtoms::spinner)
rv = NS_NewSpinnerFrame(aPresShell, &newFrame);

Просмотреть файл

@ -184,6 +184,8 @@ nsXBLBinding::kEventHandlerMap[] = {
{ "command", nsnull, &NS_GET_IID(nsIDOMMenuListener) },
{ "broadcast", nsnull, &NS_GET_IID(nsIDOMMenuListener) },
{ "commandupdate", nsnull, &NS_GET_IID(nsIDOMMenuListener) },
{ "overflow", nsnull, &NS_GET_IID(nsIDOMMenuListener) },
{ "underflow", nsnull, &NS_GET_IID(nsIDOMMenuListener) },
{ "focus", nsnull, &NS_GET_IID(nsIDOMFocusListener) },
{ "blur", nsnull, &NS_GET_IID(nsIDOMFocusListener) },
@ -1428,7 +1430,9 @@ PRBool
nsXBLBinding::IsXULHandler(const nsString& aName)
{
return ((aName.EqualsWithConversion("create")) || (aName.EqualsWithConversion("destroy")) || (aName.EqualsWithConversion("broadcast")) ||
(aName.EqualsWithConversion("command")) || (aName.EqualsWithConversion("commandupdate")) || (aName.EqualsWithConversion("close")));
(aName.EqualsWithConversion("command")) || (aName.EqualsWithConversion("commandupdate")) || (aName.EqualsWithConversion("close")) ||
(aName.EqualsWithConversion("overflow")) ||
(aName.EqualsWithConversion("underflow")) );
}
NS_IMETHODIMP

Просмотреть файл

@ -275,6 +275,24 @@ nsresult nsXBLEventHandler::CommandUpdate(nsIDOMEvent* aEvent)
return NS_OK;
}
nsresult nsXBLEventHandler::Overflow(nsIDOMEvent* aEvent)
{
if (!mEventName.EqualsWithConversion("overflow"))
return NS_OK;
ExecuteHandler(NS_ConvertASCIItoUCS2("overflow"), aEvent);
return NS_OK;
}
nsresult nsXBLEventHandler::Underflow(nsIDOMEvent* aEvent)
{
if (!mEventName.EqualsWithConversion("underflow"))
return NS_OK;
ExecuteHandler(NS_ConvertASCIItoUCS2("underflow"), aEvent);
return NS_OK;
}
nsresult nsXBLEventHandler::Destroy(nsIDOMEvent* aEvent)
{
if (!mEventName.EqualsWithConversion("destroy"))

Просмотреть файл

@ -70,6 +70,8 @@ public:
NS_IMETHOD Action(nsIDOMEvent* aEvent);
NS_IMETHOD Broadcast(nsIDOMEvent* aEvent);
NS_IMETHOD CommandUpdate(nsIDOMEvent* aEvent);
NS_IMETHOD Overflow(nsIDOMEvent* aEvent);
NS_IMETHOD Underflow(nsIDOMEvent* aEvent);
NS_DECL_ISUPPORTS

Просмотреть файл

@ -36,9 +36,11 @@ EXPORTS = \
$(NULL)
XPIDLSRCS= nsIBoxObject.idl \
nsIScrollBoxObject.idl \
nsIBoxLayoutManager.idl \
nsIBoxPaintManager.idl \
nsITreeBoxObject.idl \
nsIScrollBoxObject.idl \
nsIPopupSetBoxObject.idl \
nsIMenuBoxObject.idl \
nsIBrowserBoxObject.idl \

Просмотреть файл

@ -32,6 +32,7 @@ XPIDLSRCS= .\nsIBoxObject.idl \
.\nsIBoxLayoutManager.idl \
.\nsIBoxPaintManager.idl \
.\nsITreeBoxObject.idl \
.\nsIScrollBoxObject.idl \
.\nsIPopupSetBoxObject.idl \
.\nsIMenuBoxObject.idl \
.\nsIBrowserBoxObject.idl \

Просмотреть файл

@ -0,0 +1,49 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Original Author: Eric D. Vaughan (evaughan@netscape.com)
*
* Contributor(s):
*/
#include "nsIBoxObject.idl"
#include "domstubs.idl"
[scriptable, uuid(56E2ADA8-4631-11d4-BA11-001083023C1E)]
interface nsIScrollBoxObject : nsISupports
{
void scrollTo(in long x, in long y);
void scrollBy(in long dx, in long dy);
void scrollByLine(in long dlines);
void scrollByIndex(in long dindexes);
void scrollToLine(in long line);
void scrollToElement(in nsIDOMElement child);
void scrollToIndex(in long index);
void getPosition(out long x, out long y);
void getScrolledSize(out long width, out long height);
void ensureElementIsVisible(in nsIDOMElement child);
void ensureIndexIsVisible(in long index);
void ensureLineIsVisible(in long line);
};
%{C++
nsresult
NS_NewScrollBoxObject(nsIBoxObject** aResult);
%}

Просмотреть файл

@ -30,6 +30,8 @@ MODULE = layout
LIBRARY_NAME = raptorxulbase_s
CPPSRCS = \
nsScrollBoxObject.cpp \
nsScrollBoxFrame.cpp \
nsTreeLayout.cpp \
nsXULTreeCellFrame.cpp \
nsXULTreeFrame.cpp \
@ -41,6 +43,7 @@ CPPSRCS = \
nsEditorBoxObject.cpp \
nsMenuBoxObject.cpp \
nsTreeBoxObject.cpp \
nsScrollBoxObject.cpp \
nsPopupSetBoxObject.cpp \
nsBoxObject.cpp \
nsGridLayout.cpp \

Просмотреть файл

@ -28,10 +28,12 @@ REQUIRES=xpcom raptor pref
DEFINES=-D_IMPL_NS_HTML -DWIN32_LEAN_AND_MEAN
CPPSRCS= \
nsScrollBoxFrame.cpp \
nsEditorBoxObject.cpp \
nsIFrameBoxObject.cpp \
nsBrowserBoxObject.cpp \
nsTreeBoxObject.cpp \
nsScrollBoxObject.cpp \
nsPopupSetBoxObject.cpp \
nsMenuBoxObject.cpp \
nsBoxObject.cpp \
@ -96,10 +98,12 @@ CPPSRCS= \
$(NULL)
CPP_OBJS= \
.\$(OBJDIR)\nsScrollBoxFrame.obj \
.\$(OBJDIR)\nsEditorBoxObject.obj \
.\$(OBJDIR)\nsIFrameBoxObject.obj \
.\$(OBJDIR)\nsBrowserBoxObject.obj \
.\$(OBJDIR)\nsTreeBoxObject.obj \
.\$(OBJDIR)\nsScrollBoxObject.obj \
.\$(OBJDIR)\nsPopupSetBoxObject.obj \
.\$(OBJDIR)\nsMenuBoxObject.obj \
.\$(OBJDIR)\nsBoxObject.obj \

Просмотреть файл

@ -160,6 +160,8 @@ public:
void DrawLine(nsIRenderingContext& aRenderingContext, PRBool aHorizontal, nscoord x1, nscoord y1, nscoord x2, nscoord y2);
void FillRect(nsIRenderingContext& aRenderingContext, PRBool aHorizontal, nscoord x, nscoord y, nscoord width, nscoord height);
void CacheAttributes();
nsIBox* GetBoxForFrame(nsIFrame* aFrame, PRBool& aIsAdaptor);
nsBoxFrame::Halignment GetHAlign();
@ -170,6 +172,8 @@ public:
nsBoxFrame::Valignment mValign;
nsBoxFrame::Halignment mHalign;
PRBool mAttributesCached;
nsIPresContext* mPresContext;
@ -203,6 +207,8 @@ nsBoxFrame::nsBoxFrame(nsIPresShell* aPresShell, PRBool aIsRoot, nsIBoxLayout* a
{
mInner = new (aPresShell) nsBoxFrameInner(aPresShell, this);
mInner->mAttributesCached = PR_FALSE;
// if not otherwise specified boxes by default are horizontal.
if (aIsHorizontal) {
mState |= NS_STATE_IS_HORIZONTAL;
@ -317,43 +323,8 @@ nsBoxFrame::Init(nsIPresContext* aPresContext,
view->CreateWidget(kWidgetCID);
}
}
mInner->mValign = nsBoxFrame::vAlign_Top;
mInner->mHalign = nsBoxFrame::hAlign_Left;
GetInitialVAlignment(mInner->mValign);
GetInitialHAlignment(mInner->mHalign);
PRBool orient = PR_FALSE;
if (mState & NS_STATE_DEFAULT_HORIZONTAL)
orient = PR_TRUE;
GetInitialOrientation(orient);
if (orient)
mState |= NS_STATE_IS_HORIZONTAL;
else
mState &= ~NS_STATE_IS_HORIZONTAL;
PRBool autostretch = mState & NS_STATE_AUTO_STRETCH;
GetInitialAutoStretch(autostretch);
if (autostretch)
mState |= NS_STATE_AUTO_STRETCH;
else
mState &= ~NS_STATE_AUTO_STRETCH;
PRBool debug = mState & NS_STATE_SET_TO_DEBUG;
PRBool debugSet = mInner->GetInitialDebug(debug);
if (debugSet) {
mState |= NS_STATE_DEBUG_WAS_SET;
if (debug)
mState |= NS_STATE_SET_TO_DEBUG;
else
mState &= ~NS_STATE_SET_TO_DEBUG;
} else {
mState &= ~NS_STATE_DEBUG_WAS_SET;
}
mInner->CacheAttributes();
// if we are root and this
if (mState & NS_STATE_IS_ROOT)
@ -376,6 +347,60 @@ nsBoxFrame::Init(nsIPresContext* aPresContext,
return rv;
}
void
nsBoxFrameInner::CacheAttributes()
{
/*
printf("Caching: ");
mOuter->DumpBox(stdout);
printf("\n");
*/
mValign = nsBoxFrame::vAlign_Top;
mHalign = nsBoxFrame::hAlign_Left;
mOuter->GetInitialVAlignment(mValign);
mOuter->GetInitialHAlignment(mHalign);
PRBool orient = PR_FALSE;
if (mOuter->mState & NS_STATE_DEFAULT_HORIZONTAL)
orient = PR_TRUE;
mOuter->GetInitialOrientation(orient);
if (orient)
mOuter->mState |= NS_STATE_IS_HORIZONTAL;
else
mOuter->mState &= ~NS_STATE_IS_HORIZONTAL;
PRBool equalSize = PR_FALSE;
mOuter->GetInitialEqualSize(equalSize);
if (equalSize)
mOuter->mState |= NS_STATE_EQUAL_SIZE;
else
mOuter->mState &= ~NS_STATE_EQUAL_SIZE;
PRBool autostretch = mOuter->mState & NS_STATE_AUTO_STRETCH;
mOuter->GetInitialAutoStretch(autostretch);
if (autostretch)
mOuter->mState |= NS_STATE_AUTO_STRETCH;
else
mOuter->mState &= ~NS_STATE_AUTO_STRETCH;
PRBool debug = mOuter->mState & NS_STATE_SET_TO_DEBUG;
PRBool debugSet = GetInitialDebug(debug);
if (debugSet) {
mOuter->mState |= NS_STATE_DEBUG_WAS_SET;
if (debug)
mOuter->mState |= NS_STATE_SET_TO_DEBUG;
else
mOuter->mState &= ~NS_STATE_SET_TO_DEBUG;
} else {
mOuter->mState &= ~NS_STATE_DEBUG_WAS_SET;
}
}
PRBool
nsBoxFrameInner::GetInitialDebug(PRBool& aDebug)
{
@ -553,6 +578,31 @@ nsBoxFrame::GetInitialOrientation(PRBool& aIsHorizontal)
return PR_FALSE;
}
/* Returns true if it was set.
*/
PRBool
nsBoxFrame::GetInitialEqualSize(PRBool& aEqualSize)
{
// see if we are a vertical or horizontal box.
nsAutoString value;
nsCOMPtr<nsIContent> content;
GetContentOf(getter_AddRefs(content));
if (!content)
return PR_FALSE;
if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsXULAtoms::equalsize, value))
{
if (value.EqualsIgnoreCase("always")) {
aEqualSize = PR_TRUE;
return PR_TRUE;
}
}
return PR_FALSE;
}
/* Returns true if it was set.
*/
PRBool
@ -662,10 +712,7 @@ nsBoxFrame::Reflow(nsIPresContext* aPresContext,
else
computedSize.height += m.top + m.bottom;
nsRect r(0,0,computedSize.width, computedSize.height);
//r.Inflate(m);
r.x = mRect.x;
r.y = mRect.y;
nsRect r(mRect.x, mRect.y, computedSize.width, computedSize.height);
SetBounds(state, r);
@ -773,6 +820,14 @@ nsBoxFrame::GetMaxSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize)
return NS_OK;
}
/*
// @@@ hack to fix bug in xbl where it won't set flex -EDV
if ((mState & NS_FRAME_FIRST_REFLOW) && !mInner->mAttributesCached) {
mInner->CacheAttributes();
mInner->mAttributesCached = PR_TRUE;
}
*/
PropagateDebug(aBoxLayoutState);
nsresult rv = NS_OK;
@ -819,6 +874,7 @@ nsBoxFrame::PropagateDebug(nsBoxLayoutState& aState)
NS_IMETHODIMP
nsBoxFrame::Layout(nsBoxLayoutState& aState)
{
// mark ourselves as dirty so no child under us
// can post an incremental layout.
mState |= NS_FRAME_HAS_DIRTY_CHILDREN;
@ -1012,6 +1068,7 @@ nsBoxFrame::AttributeChanged(nsIPresContext* aPresContext,
aAttribute == nsHTMLAtoms::valign ||
aAttribute == nsXULAtoms::flex ||
aAttribute == nsXULAtoms::orient ||
aAttribute == nsXULAtoms::equalsize ||
aAttribute == nsXULAtoms::autostretch) {
if (aAttribute == nsXULAtoms::orient || aAttribute == nsXULAtoms::debug || aAttribute == nsHTMLAtoms::align || aAttribute == nsHTMLAtoms::valign) {
@ -1021,13 +1078,20 @@ nsBoxFrame::AttributeChanged(nsIPresContext* aPresContext,
GetInitialVAlignment(mInner->mValign);
GetInitialHAlignment(mInner->mHalign);
PRBool orient = mState & NS_STATE_IS_HORIZONTAL;
PRBool orient = mState & NS_STATE_DEFAULT_HORIZONTAL;
GetInitialOrientation(orient);
if (orient)
mState |= NS_STATE_IS_HORIZONTAL;
else
mState &= ~NS_STATE_IS_HORIZONTAL;
PRBool equalSize = PR_FALSE;
GetInitialEqualSize(equalSize);
if (equalSize)
mState |= NS_STATE_EQUAL_SIZE;
else
mState &= ~NS_STATE_EQUAL_SIZE;
PRBool debug = mState & NS_STATE_SET_TO_DEBUG;
PRBool debugSet = mInner->GetInitialDebug(debug);
if (debugSet) {

Просмотреть файл

@ -58,6 +58,7 @@ class nsHTMLInfo;
#define NS_STATE_IS_COLLAPSED 0x10000000
#define NS_STATE_DEFAULT_HORIZONTAL 0x20000000
#define NS_STATE_STYLE_CHANGE 0x40000000
#define NS_STATE_EQUAL_SIZE 0x80000000
class nsBoxFrame : public nsHTMLContainerFrame, public nsContainerBox
{
@ -194,6 +195,7 @@ protected:
virtual PRIntn GetSkipSides() const { return 0; }
virtual PRBool GetInitialEqualSize(PRBool& aEqualSize);
virtual PRBool GetInitialOrientation(PRBool& aIsHorizontal);
virtual PRBool GetInitialHAlignment(Halignment& aHalign);
virtual PRBool GetInitialVAlignment(Valignment& aValign);

Просмотреть файл

@ -0,0 +1,825 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Author: Eric D Vaughan (evaughan@netscape.com)
*
* Contributor(s):
* Pierre Phaneuf <pp@ludusdesign.com>
*/
#include "nsCOMPtr.h"
#include "nsHTMLParts.h"
#include "nsIPresContext.h"
#include "nsIStyleContext.h"
#include "nsIReflowCommand.h"
#include "nsIDeviceContext.h"
#include "nsPageFrame.h"
#include "nsViewsCID.h"
#include "nsIView.h"
#include "nsIViewManager.h"
#include "nsHTMLContainerFrame.h"
#include "nsHTMLIIDs.h"
#include "nsCSSRendering.h"
#include "nsIScrollableView.h"
#include "nsWidgetsCID.h"
#include "nsScrollBoxFrame.h"
#include "nsLayoutAtoms.h"
#include "nsIBox.h"
#include "nsBoxLayoutState.h"
#include "nsIBoxToBlockAdaptor.h"
#include "nsISupportsPrimitives.h"
#include "nsIPresState.h"
#include "nsButtonBoxFrame.h"
#include "nsITimerCallback.h"
#include "nsRepeatService.h"
static NS_DEFINE_IID(kWidgetCID, NS_CHILD_CID);
static NS_DEFINE_IID(kScrollBoxViewCID, NS_SCROLL_PORT_VIEW_CID);
static NS_DEFINE_IID(kViewCID, NS_VIEW_CID);
static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID);
static NS_DEFINE_IID(kScrollViewIID, NS_ISCROLLABLEVIEW_IID);
//----------------------------------------------------------------------
nsresult
NS_NewScrollBoxFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsScrollBoxFrame* it = new (aPresShell) nsScrollBoxFrame (aPresShell);
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
*aNewFrame = it;
return NS_OK;
}
nsScrollBoxFrame::nsScrollBoxFrame(nsIPresShell* aShell):nsBoxFrame(aShell), mVerticalOverflow(PR_FALSE), mHorizontalOverflow(PR_FALSE)
{
}
PRBool
nsScrollBoxFrame::NeedsClipWidget()
{
return PR_TRUE;
}
NS_IMETHODIMP
nsScrollBoxFrame::Init(nsIPresContext* aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aStyleContext,
nsIFrame* aPrevInFlow)
{
nsresult rv = nsBoxFrame::Init(aPresContext, aContent,
aParent, aStyleContext,
aPrevInFlow);
// Create the scrolling view
CreateScrollingView(aPresContext);
return rv;
}
NS_IMETHODIMP
nsScrollBoxFrame::SetInitialChildList(nsIPresContext* aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList)
{
nsresult rv = nsBoxFrame::SetInitialChildList(aPresContext, aListName,
aChildList);
SetUpScrolledFrame(aPresContext);
return rv;
}
void
nsScrollBoxFrame::SetUpScrolledFrame(nsIPresContext* aPresContext)
{
NS_ASSERTION(mFrames.GetLength() <= 1, "ScrollBoxes can only have 1 child!");
nsIFrame* frame = mFrames.FirstChild();
if (!frame)
return;
// create a view if we don't already have one.
nsCOMPtr<nsIStyleContext> context;
frame->GetStyleContext(getter_AddRefs(context));
nsHTMLContainerFrame::CreateViewForFrame(aPresContext, frame,
context, PR_TRUE);
// We need to allow the view's position to be different than the
// frame's position
nsFrameState state;
frame->GetFrameState(&state);
state &= ~NS_FRAME_SYNC_FRAME_AND_VIEW;
frame->SetFrameState(state);
}
NS_IMETHODIMP
nsScrollBoxFrame::AppendFrames(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aFrameList)
{
nsresult rv = nsBoxFrame::AppendFrames(aPresContext, aPresShell, aListName, aFrameList);
#ifdef DEBUG
// make sure we only have 1 child.
nsIFrame* frame = mFrames.FirstChild();
frame->GetNextSibling(&frame);
NS_ASSERTION(!frame, "Error ScrollBoxes can only have 1 child");
#endif
SetUpScrolledFrame(aPresContext);
return rv;
}
NS_IMETHODIMP
nsScrollBoxFrame::InsertFrames(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aPrevFrame,
nsIFrame* aFrameList)
{
nsresult rv = nsBoxFrame::InsertFrames(aPresContext, aPresShell, aListName, aPrevFrame, aFrameList);
#ifdef DEBUG
// make sure we only have 1 child.
nsIFrame* frame = mFrames.FirstChild();
frame->GetNextSibling(&frame);
NS_ASSERTION(!frame, "Error ScrollBoxes can only have 1 child");
#endif
SetUpScrolledFrame(aPresContext);
return rv;
}
NS_IMETHODIMP
nsScrollBoxFrame::RemoveFrame(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aOldFrame)
{
nsresult rv = nsBoxFrame::RemoveFrame(aPresContext, aPresShell, aListName, aOldFrame);
SetUpScrolledFrame(aPresContext);
return rv;
}
nsresult
nsScrollBoxFrame::CreateScrollingViewWidget(nsIView* aView, const nsStylePosition* aPosition)
{
nsresult rv = NS_OK;
// If it's fixed positioned, then create a widget
if (NS_STYLE_POSITION_FIXED == aPosition->mPosition) {
rv = aView->CreateWidget(kWidgetCID);
}
return(rv);
}
nsresult
nsScrollBoxFrame::GetScrollingParentView(nsIPresContext* aPresContext,
nsIFrame* aParent,
nsIView** aParentView)
{
nsresult rv = aParent->GetView(aPresContext, aParentView);
NS_ASSERTION(aParentView, "GetParentWithView failed");
return(rv);
}
nsresult
nsScrollBoxFrame::CreateScrollingView(nsIPresContext* aPresContext)
{
nsIView* view;
//Get parent frame
nsIFrame* parent;
GetParentWithView(aPresContext, &parent);
NS_ASSERTION(parent, "GetParentWithView failed");
// Get parent view
nsIView* parentView = nsnull;
GetScrollingParentView(aPresContext, parent, &parentView);
// Get the view manager
nsIViewManager* viewManager;
parentView->GetViewManager(viewManager);
// Create the scrolling view
nsresult rv = nsComponentManager::CreateInstance(kScrollBoxViewCID,
nsnull,
kIViewIID,
(void **)&view);
if (NS_OK == rv) {
const nsStylePosition* position = (const nsStylePosition*)
mStyleContext->GetStyleData(eStyleStruct_Position);
const nsStyleColor* color = (const nsStyleColor*)
mStyleContext->GetStyleData(eStyleStruct_Color);
const nsStyleSpacing* spacing = (const nsStyleSpacing*)
mStyleContext->GetStyleData(eStyleStruct_Spacing);
const nsStyleDisplay* display = (const nsStyleDisplay*)
mStyleContext->GetStyleData(eStyleStruct_Display);
// Get the z-index
PRInt32 zIndex = 0;
if (eStyleUnit_Integer == position->mZIndex.GetUnit()) {
zIndex = position->mZIndex.GetIntValue();
}
// Initialize the scrolling view
view->Init(viewManager, mRect, parentView, display->IsVisibleOrCollapsed() ?
nsViewVisibility_kShow : nsViewVisibility_kHide);
// Insert the view into the view hierarchy
viewManager->InsertChild(parentView, view, zIndex);
// Set the view's opacity
viewManager->SetViewOpacity(view, color->mOpacity);
// Because we only paint the border and we don't paint a background,
// inform the view manager that we have transparent content
viewManager->SetViewContentTransparency(view, PR_TRUE);
// If it's fixed positioned, then create a widget too
CreateScrollingViewWidget(view, position);
// Get the nsIScrollableView interface
nsIScrollableView* scrollingView;
view->QueryInterface(kScrollViewIID, (void**)&scrollingView);
scrollingView->SetScrollPreference(nsScrollPreference_kNeverScroll);
// Have the scrolling view create its internal widgets
scrollingView->CreateScrollControls();
// Set the scrolling view's insets to whatever our border is
nsMargin border;
if (!spacing->GetBorder(border)) {
NS_NOTYETIMPLEMENTED("percentage border");
border.SizeTo(0, 0, 0, 0);
}
scrollingView->SetControlInsets(border);
// Remember our view
SetView(aPresContext, view);
}
NS_RELEASE(viewManager);
return rv;
}
NS_IMETHODIMP
nsScrollBoxFrame::GetMargin(nsMargin& aMargin)
{
aMargin.SizeTo(0,0,0,0);
return NS_OK;
}
NS_IMETHODIMP
nsScrollBoxFrame::GetPadding(nsMargin& aMargin)
{
aMargin.SizeTo(0,0,0,0);
return NS_OK;
}
NS_IMETHODIMP
nsScrollBoxFrame::GetBorder(nsMargin& aMargin)
{
aMargin.SizeTo(0,0,0,0);
return NS_OK;
}
NS_IMETHODIMP
nsScrollBoxFrame::Layout(nsBoxLayoutState& aState)
{
PRUint32 flags = 0;
aState.GetLayoutFlags(flags);
nsRect clientRect(0,0,0,0);
GetClientRect(clientRect);
nsIBox* kid = nsnull;
GetChildBox(&kid);
nsRect childRect(clientRect);
nsMargin margin(0,0,0,0);
kid->GetMargin(margin);
childRect.Deflate(margin);
nsSize min(0,0);
kid->GetMinSize(aState, min);
/*
// if our child is not html then get is min size
// and make sure we don't squeeze it smaller than that.
nsIBoxToBlockAdaptor* adaptor = nsnull;
if (NS_FAILED(kid->QueryInterface(NS_GET_IID(nsIBoxToBlockAdaptor), (void**)&adaptor))) {
if (min.height > childRect.height)
childRect.height = min.height;
}
*/
if (min.height > childRect.height)
childRect.height = min.height;
if (min.width > childRect.width)
childRect.width = min.width;
aState.SetLayoutFlags(NS_FRAME_NO_MOVE_VIEW);
kid->SetBounds(aState, childRect);
kid->Layout(aState);
kid->GetBounds(childRect);
clientRect.Inflate(margin);
if (childRect.width < clientRect.width || childRect.height < childRect.height)
{
if (childRect.width < clientRect.width)
childRect.width = clientRect.width;
if (childRect.height < clientRect.height)
childRect.height = clientRect.height;
clientRect.Deflate(margin);
kid->SetBounds(aState, childRect);
}
aState.SetLayoutFlags(flags);
SyncLayout(aState);
nsIPresContext* presContext = aState.GetPresContext();
nsIScrollableView* scrollingView;
nsIView* view;
GetView(presContext, &view);
if (NS_SUCCEEDED(view->QueryInterface(kScrollViewIID, (void**)&scrollingView))) {
scrollingView->ComputeScrollOffsets(PR_TRUE);
}
nsRect scrollPort;
GetBounds(scrollPort);
kid->GetBounds(childRect);
// first see what changed
PRBool vertChanged = PR_FALSE;
PRBool horizChanged = PR_FALSE;
if (mVerticalOverflow && childRect.height <= scrollPort.height) {
mVerticalOverflow = PR_FALSE;
vertChanged = PR_TRUE;
} else if (!mVerticalOverflow && childRect.height > scrollPort.height) {
mVerticalOverflow = PR_TRUE;
vertChanged = PR_TRUE;
}
if (mHorizontalOverflow && childRect.width <= scrollPort.width) {
mHorizontalOverflow = PR_FALSE;
horizChanged = PR_TRUE;
} else if (!mHorizontalOverflow && childRect.width > scrollPort.width) {
mHorizontalOverflow = PR_TRUE;
horizChanged = PR_TRUE;
}
nsCOMPtr<nsIPresShell> shell;
aState.GetPresShell(getter_AddRefs(shell));
// if either changed
if (vertChanged || horizChanged)
{
// are there 2 events or 1?
if (vertChanged && horizChanged) {
if (mVerticalOverflow == mHorizontalOverflow)
{
// both either overflowed or underflowed. 1 event
PostScrollPortEvent(shell, mVerticalOverflow, nsScrollPortEvent::both);
} else {
// one overflowed and one underflowed
PostScrollPortEvent(shell, mVerticalOverflow, nsScrollPortEvent::vertical);
PostScrollPortEvent(shell, mHorizontalOverflow, nsScrollPortEvent::horizontal);
}
} else if (vertChanged) // only one changed either vert or horiz
PostScrollPortEvent(shell, mVerticalOverflow, nsScrollPortEvent::vertical);
else
PostScrollPortEvent(shell, mHorizontalOverflow, nsScrollPortEvent::horizontal);
}
return NS_OK;
}
void
nsScrollBoxFrame::PostScrollPortEvent(nsIPresShell* aShell, PRBool aOverflow, nsScrollPortEvent::orientType aType)
{
if (!mContent)
return;
nsScrollPortEvent* event = new nsScrollPortEvent();
event->eventStructType = NS_SCROLLPORT_EVENT;
event->widget = nsnull;
event->orient = aType;
event->nativeMsg = nsnull;
event->message = aOverflow ? NS_SCROLLPORT_OVERFLOW : NS_SCROLLPORT_UNDERFLOW;
aShell->PostDOMEvent(mContent, event);
}
NS_IMETHODIMP
nsScrollBoxFrame::GetAscent(nsBoxLayoutState& aState, nscoord& aAscent)
{
aAscent = 0;
nsIBox* child = nsnull;
GetChildBox(&child);
nsresult rv = child->GetAscent(aState, aAscent);
nsMargin m(0,0,0,0);
GetBorderAndPadding(m);
aAscent += m.top;
GetMargin(m);
aAscent += m.top;
GetInset(m);
aAscent += m.top;
return rv;
}
NS_IMETHODIMP
nsScrollBoxFrame::GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize)
{
nsIBox* child = nsnull;
GetChildBox(&child);
nsresult rv = child->GetPrefSize(aBoxLayoutState, aSize);
AddMargin(child, aSize);
AddBorderAndPadding(aSize);
AddInset(aSize);
nsIBox::AddCSSPrefSize(aBoxLayoutState, this, aSize);
return rv;
}
NS_IMETHODIMP
nsScrollBoxFrame::GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize)
{
aSize.width = 0;
aSize.height = 0;
AddBorderAndPadding(aSize);
AddInset(aSize);
nsIBox::AddCSSMinSize(aBoxLayoutState, this, aSize);
return NS_OK;
}
NS_IMETHODIMP
nsScrollBoxFrame::GetMaxSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize)
{
nsIBox* child = nsnull;
GetChildBox(&child);
nsresult rv = child->GetMaxSize(aBoxLayoutState, aSize);
AddMargin(child, aSize);
AddBorderAndPadding(aSize);
AddInset(aSize);
nsIBox::AddCSSMaxSize(aBoxLayoutState, this, aSize);
return rv;
}
NS_IMETHODIMP
nsScrollBoxFrame::Paint(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer)
{
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
// Only paint the border and background if we're visible
const nsStyleDisplay* display = (const nsStyleDisplay*)
mStyleContext->GetStyleData(eStyleStruct_Display);
if (display->IsVisibleOrCollapsed()) {
// Paint our border only (no background)
const nsStyleSpacing* spacing = (const nsStyleSpacing*)
mStyleContext->GetStyleData(eStyleStruct_Spacing);
nsRect rect(0, 0, mRect.width, mRect.height);
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *spacing, mStyleContext, 0);
}
}
// Paint our children
nsresult rv = nsBoxFrame::Paint(aPresContext, aRenderingContext, aDirtyRect,
aWhichLayer);
return rv;
}
PRIntn
nsScrollBoxFrame::GetSkipSides() const
{
return 0;
}
nsresult
nsScrollBoxFrame::GetContentOf(nsIContent** aContent)
{
return GetContent(aContent);
}
NS_IMETHODIMP
nsScrollBoxFrame::GetFrameType(nsIAtom** aType) const
{
NS_PRECONDITION(nsnull != aType, "null OUT parameter pointer");
*aType = nsLayoutAtoms::scrollFrame;
NS_ADDREF(*aType);
return NS_OK;
}
#ifdef NS_DEBUG
NS_IMETHODIMP
nsScrollBoxFrame::GetFrameName(nsString& aResult) const
{
return MakeFrameName("ScrollBox", aResult);
}
#endif
NS_IMETHODIMP_(nsrefcnt)
nsScrollBoxFrame::AddRef(void)
{
return NS_OK;
}
NS_IMETHODIMP_(nsrefcnt)
nsScrollBoxFrame::Release(void)
{
return NS_OK;
}
//----------------------------------------------------------------------
// nsIStatefulFrame
//----------------------------------------------------------------------
NS_IMETHODIMP
nsScrollBoxFrame::GetStateType(nsIPresContext* aPresContext,
nsIStatefulFrame::StateType* aStateType)
{
*aStateType = nsIStatefulFrame::eScrollType;
return NS_OK;
}
//----------------------------------------------------------------------
NS_IMETHODIMP
nsScrollBoxFrame::SaveState(nsIPresContext* aPresContext,
nsIPresState** aState)
{
nsresult res = NS_OK;
PRInt32 x,y;
nsIScrollableView* scrollingView;
nsIView* view;
GetView(aPresContext, &view);
if (NS_SUCCEEDED(view->QueryInterface(kScrollViewIID, (void**)&scrollingView))) {
scrollingView->GetScrollPosition(x,y);
}
nsIView* child = nsnull;
nsRect childRect(0,0,0,0);
if (NS_SUCCEEDED(scrollingView->GetScrolledView(child)) && child) {
child->GetBounds(childRect);
}
res = NS_NewPresState(aState);
nsCOMPtr<nsISupportsPRInt32> xoffset;
if (NS_SUCCEEDED(res)) {
res = nsComponentManager::CreateInstance(NS_SUPPORTS_PRINT32_PROGID,
nsnull, NS_GET_IID(nsISupportsPRInt32), (void**)getter_AddRefs(xoffset));
if (NS_SUCCEEDED(res) && xoffset) {
res = xoffset->SetData(x);
if (NS_SUCCEEDED(res)) {
(*aState)->SetStatePropertyAsSupports(NS_ConvertASCIItoUCS2("x-offset"), xoffset);
}
}
}
nsCOMPtr<nsISupportsPRInt32> yoffset;
if (NS_SUCCEEDED(res)) {
res = nsComponentManager::CreateInstance(NS_SUPPORTS_PRINT32_PROGID,
nsnull, NS_GET_IID(nsISupportsPRInt32), (void**)getter_AddRefs(yoffset));
if (NS_SUCCEEDED(res) && yoffset) {
res = yoffset->SetData(y);
if (NS_SUCCEEDED(res)) {
(*aState)->SetStatePropertyAsSupports(NS_ConvertASCIItoUCS2("y-offset"), yoffset);
}
}
}
nsCOMPtr<nsISupportsPRInt32> width;
if (NS_SUCCEEDED(res)) {
res = nsComponentManager::CreateInstance(NS_SUPPORTS_PRINT32_PROGID,
nsnull, NS_GET_IID(nsISupportsPRInt32), (void**)getter_AddRefs(width));
if (NS_SUCCEEDED(res) && width) {
res = width->SetData(childRect.width);
if (NS_SUCCEEDED(res)) {
(*aState)->SetStatePropertyAsSupports(NS_ConvertASCIItoUCS2("width"), width);
}
}
}
nsCOMPtr<nsISupportsPRInt32> height;
if (NS_SUCCEEDED(res)) {
res = nsComponentManager::CreateInstance(NS_SUPPORTS_PRINT32_PROGID,
nsnull, NS_GET_IID(nsISupportsPRInt32), (void**)getter_AddRefs(height));
if (NS_SUCCEEDED(res) && height) {
res = height->SetData(childRect.height);
if (NS_SUCCEEDED(res)) {
(*aState)->SetStatePropertyAsSupports(NS_ConvertASCIItoUCS2("height"), height);
}
}
}
return res;
}
//-----------------------------------------------------------
NS_IMETHODIMP
nsScrollBoxFrame::RestoreState(nsIPresContext* aPresContext,
nsIPresState* aState)
{
nsCOMPtr<nsISupportsPRInt32> xoffset;
nsCOMPtr<nsISupportsPRInt32> yoffset;
nsCOMPtr<nsISupportsPRInt32> width;
nsCOMPtr<nsISupportsPRInt32> height;
aState->GetStatePropertyAsSupports(NS_ConvertASCIItoUCS2("x-offset"), getter_AddRefs(xoffset));
aState->GetStatePropertyAsSupports(NS_ConvertASCIItoUCS2("y-offset"), getter_AddRefs(yoffset));
aState->GetStatePropertyAsSupports(NS_ConvertASCIItoUCS2("width"), getter_AddRefs(width));
aState->GetStatePropertyAsSupports(NS_ConvertASCIItoUCS2("height"), getter_AddRefs(height));
nsresult res = NS_ERROR_NULL_POINTER;
if (xoffset && yoffset) {
PRInt32 x,y,w,h;
res = xoffset->GetData(&x);
if (NS_SUCCEEDED(res))
res = yoffset->GetData(&y);
if (NS_SUCCEEDED(res))
res = width->GetData(&w);
if (NS_SUCCEEDED(res))
res = height->GetData(&h);
if (NS_SUCCEEDED(res)) {
nsIScrollableView* scrollingView;
nsIView* view;
GetView(aPresContext, &view);
if (NS_SUCCEEDED(view->QueryInterface(kScrollViewIID, (void**)&scrollingView))) {
nsIView* child = nsnull;
nsRect childRect(0,0,0,0);
if (NS_SUCCEEDED(scrollingView->GetScrolledView(child)) && child) {
child->GetBounds(childRect);
}
x = (int)(((float)childRect.width / w) * x);
y = (int)(((float)childRect.height / h) * y);
scrollingView->ScrollTo(x,y,0);
}
}
}
return res;
}
NS_INTERFACE_MAP_BEGIN(nsScrollBoxFrame)
NS_INTERFACE_MAP_ENTRY(nsIBox)
NS_INTERFACE_MAP_ENTRY(nsIStatefulFrame)
#ifdef NS_DEBUG
NS_INTERFACE_MAP_ENTRY(nsIFrameDebug)
#endif
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIBox)
NS_INTERFACE_MAP_END_INHERITING(nsBoxFrame)
class nsAutoRepeatBoxFrame : public nsButtonBoxFrame,
public nsITimerCallback
{
public:
NS_DECL_ISUPPORTS_INHERITED
nsAutoRepeatBoxFrame(nsIPresShell* aPresShell);
friend nsresult NS_NewAutoRepeatBoxFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
NS_IMETHOD Destroy(nsIPresContext* aPresContext);
NS_IMETHOD HandleEvent(nsIPresContext* aPresContext,
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus);
NS_IMETHOD Init(nsIPresContext* aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow);
NS_IMETHOD_(void) Notify(nsITimer *timer);
nsIPresContext* mPresContext;
};
nsresult
NS_NewAutoRepeatBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame )
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsAutoRepeatBoxFrame* it = new (aPresShell) nsAutoRepeatBoxFrame (aPresShell);
if (nsnull == it)
return NS_ERROR_OUT_OF_MEMORY;
*aNewFrame = it;
return NS_OK;
} // NS_NewScrollBarButtonFrame
nsAutoRepeatBoxFrame::nsAutoRepeatBoxFrame(nsIPresShell* aPresShell)
:nsButtonBoxFrame(aPresShell)
{
}
NS_IMETHODIMP
nsAutoRepeatBoxFrame::Init(nsIPresContext* aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow)
{
mPresContext = aPresContext;
return nsButtonBoxFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
}
NS_INTERFACE_MAP_BEGIN(nsAutoRepeatBoxFrame)
NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
NS_INTERFACE_MAP_END_INHERITING(nsButtonBoxFrame)
NS_IMPL_ADDREF_INHERITED(nsAutoRepeatBoxFrame, nsButtonBoxFrame)
NS_IMPL_RELEASE_INHERITED(nsAutoRepeatBoxFrame, nsButtonBoxFrame)
NS_IMETHODIMP
nsAutoRepeatBoxFrame::HandleEvent(nsIPresContext* aPresContext,
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus)
{
switch(aEvent->message)
{
case NS_MOUSE_ENTER:
case NS_MOUSE_ENTER_SYNTH:
nsRepeatService::GetInstance()->Start(this);
break;
case NS_MOUSE_EXIT:
case NS_MOUSE_EXIT_SYNTH:
nsRepeatService::GetInstance()->Stop();
break;
}
return nsButtonBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
}
NS_IMETHODIMP_(void)
nsAutoRepeatBoxFrame::Notify(nsITimer *timer)
{
MouseClicked(mPresContext);
}
NS_IMETHODIMP
nsAutoRepeatBoxFrame::Destroy(nsIPresContext* aPresContext)
{
// Ensure our repeat service isn't going... it's possible that a scrollbar can disappear out
// from under you while you're in the process of scrolling.
nsRepeatService::GetInstance()->Stop();
return nsButtonBoxFrame::Destroy(aPresContext);
}

Просмотреть файл

@ -0,0 +1,132 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsScrollBoxFrame_h___
#define nsScrollBoxFrame_h___
#include "nsBoxFrame.h"
#include "nsIStatefulFrame.h"
#include "nsGUIEvent.h"
/**
* The scroll frame creates and manages the scrolling view
*
* It only supports having a single child frame that typically is an area
* frame, but doesn't have to be. The child frame must have a view, though
*
* Scroll frames don't support incremental changes, i.e. you can't replace
* or remove the scrolled frame
*/
class nsScrollBoxFrame : public nsBoxFrame, public nsIStatefulFrame {
public:
friend nsresult NS_NewScrollBoxFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
NS_IMETHOD Init(nsIPresContext* aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow);
// Called to set the one and only child frame. Returns NS_ERROR_INVALID_ARG
// if the child frame is NULL, and NS_ERROR_UNEXPECTED if the child list
// contains more than one frame
NS_IMETHOD SetInitialChildList(nsIPresContext* aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList);
// Because there can be only one child frame, these two function return
// NS_ERROR_FAILURE
NS_IMETHOD AppendFrames(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aFrameList);
NS_IMETHOD InsertFrames(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aPrevFrame,
nsIFrame* aFrameList);
// This function returns NS_ERROR_NOT_IMPLEMENTED
NS_IMETHOD RemoveFrame(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aOldFrame);
NS_IMETHOD Paint(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer);
/**
* Get the "type" of the frame
*
* @see nsLayoutAtoms::scrollFrame
*/
NS_IMETHOD GetFrameType(nsIAtom** aType) const;
#ifdef NS_DEBUG
NS_IMETHOD GetFrameName(nsString& aResult) const;
#endif
// nsIBox methods
NS_DECL_ISUPPORTS
NS_IMETHOD GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize);
NS_IMETHOD GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize);
NS_IMETHOD GetMaxSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize);
NS_IMETHOD GetAscent(nsBoxLayoutState& aBoxLayoutState, nscoord& aAscent);
NS_IMETHOD Layout(nsBoxLayoutState& aBoxLayoutState);
NS_IMETHOD GetPadding(nsMargin& aMargin);
NS_IMETHOD GetBorder(nsMargin& aMargin);
NS_IMETHOD GetMargin(nsMargin& aMargin);
virtual nsresult GetContentOf(nsIContent** aContent);
protected:
nsScrollBoxFrame(nsIPresShell* aShell);
virtual PRIntn GetSkipSides() const;
// Creation of the widget for the scrolling view is factored into a virtual method so
// that sub-classes may control widget creation.
virtual nsresult CreateScrollingViewWidget(nsIView* aView,const nsStylePosition* aPosition);
// Getting the view for scollframe may be overriden to provide a parent view for te scroll frame
virtual nsresult GetScrollingParentView(nsIPresContext* aPresContext,
nsIFrame* aParent,
nsIView** aParentView);
//nsIStatefulFrame
NS_IMETHOD GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType);
NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState);
NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState);
private:
nsresult CreateScrollingView(nsIPresContext* aPresContext);
PRBool mVerticalOverflow;
PRBool mHorizontalOverflow;
protected:
virtual PRBool NeedsClipWidget();
virtual void PostScrollPortEvent(nsIPresShell* aShell, PRBool aOverflow, nsScrollPortEvent::orientType aType);
virtual void SetUpScrolledFrame(nsIPresContext* aPresContext);
};
#endif /* nsScrollBoxFrame_h___ */

Просмотреть файл

@ -0,0 +1,452 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Original Author: David W. Hyatt (hyatt@netscape.com)
*
* Contributor(s):
*/
#include "nsCOMPtr.h"
#include "nsIScrollBoxObject.h"
#include "nsBoxObject.h"
#include "nsIPresShell.h"
#include "nsIContent.h"
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
#include "nsIDOMElement.h"
#include "nsIPresContext.h"
#include "nsIFrame.h"
#include "nsIScrollableView.h"
#include "nsIBox.h"
static NS_DEFINE_IID(kScrollViewIID, NS_ISCROLLABLEVIEW_IID);
class nsScrollBoxObject : public nsIScrollBoxObject, public nsBoxObject
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSISCROLLBOXOBJECT
nsScrollBoxObject();
virtual ~nsScrollBoxObject();
virtual nsIScrollableView* GetScrollableView();
/* additional members */
};
/* Implementation file */
NS_INTERFACE_MAP_BEGIN(nsScrollBoxObject)
NS_INTERFACE_MAP_ENTRY(nsIScrollBoxObject)
NS_INTERFACE_MAP_END_INHERITING(nsBoxObject)
NS_IMPL_ADDREF_INHERITED(nsScrollBoxObject, nsBoxObject)
NS_IMPL_RELEASE_INHERITED(nsScrollBoxObject, nsBoxObject)
nsScrollBoxObject::nsScrollBoxObject()
{
NS_INIT_ISUPPORTS();
/* member initializers and constructor code */
}
nsScrollBoxObject::~nsScrollBoxObject()
{
/* destructor code */
}
/* void scrollTo (in long x, in long y); */
NS_IMETHODIMP nsScrollBoxObject::ScrollTo(PRInt32 x, PRInt32 y)
{
nsIScrollableView* scrollableView = GetScrollableView();
if (!scrollableView)
return NS_ERROR_FAILURE;
return scrollableView->ScrollTo(x,y, NS_SCROLL_PROPERTY_ALWAYS_BLIT);
}
/* void scrollBy (in long dx, in long dy); */
NS_IMETHODIMP nsScrollBoxObject::ScrollBy(PRInt32 dx, PRInt32 dy)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void scrollByLine (in long dlines); */
NS_IMETHODIMP nsScrollBoxObject::ScrollByLine(PRInt32 dlines)
{
nsIScrollableView* scrollableView = GetScrollableView();
if (!scrollableView)
return NS_ERROR_FAILURE;
return scrollableView->ScrollByLines(0, dlines);
}
/* void scrollByIndex (in long dindexes); */
NS_IMETHODIMP nsScrollBoxObject::ScrollByIndex(PRInt32 dindexes)
{
nsIScrollableView* scrollableView = GetScrollableView();
if (!scrollableView)
return NS_ERROR_FAILURE;
// get our box
nsIFrame* frame = GetFrame();
nsCOMPtr<nsIBox> box (do_QueryInterface(frame));
nsRect rect;
nsIBox* scrolledBox;
nsIBox* child;
// get the scrolled box
box->GetChildBox(&scrolledBox);
// now get the scrolled boxes first child.
scrolledBox->GetChildBox(&child);
PRBool horiz = PR_FALSE;
scrolledBox->GetOrientation(horiz);
nsPoint cp;
scrollableView->GetScrollPosition(cp.x,cp.y);
nscoord diff = 0;
PRInt32 curIndex = 0;
// first find out what index we are currently at
while(child) {
child->GetBounds(rect);
if (horiz) {
diff = rect.x + rect.width;
if (diff > cp.x) {
break;
}
} else {
diff = rect.y + rect.height;
if (diff > cp.y) {
break;
}
}
child->GetNextBox(&child);
curIndex++;
}
PRInt32 count = 0;
if (dindexes == 0)
return NS_OK;
if (dindexes > 0) {
while(child) {
child->GetNextBox(&child);
child->GetBounds(rect);
count++;
if (count >= dindexes)
break;
}
} else if (dindexes < 0) {
scrolledBox->GetChildBox(&child);
while(child) {
child->GetBounds(rect);
if (count >= curIndex + dindexes)
break;
count++;
child->GetNextBox(&child);
}
}
if (horiz)
return scrollableView->ScrollTo(rect.x, cp.y, NS_SCROLL_PROPERTY_ALWAYS_BLIT);
else
return scrollableView->ScrollTo(cp.x, rect.y, NS_SCROLL_PROPERTY_ALWAYS_BLIT);
}
/* void scrollToLine (in long line); */
NS_IMETHODIMP nsScrollBoxObject::ScrollToLine(PRInt32 line)
{
nsIScrollableView* scrollableView = GetScrollableView();
if (!scrollableView)
return NS_ERROR_FAILURE;
nscoord height = 0;
scrollableView->GetLineHeight(&height);
scrollableView->ScrollTo(0,height*line, NS_SCROLL_PROPERTY_ALWAYS_BLIT);
return NS_OK;
}
/* void scrollToElement (in nsIDOMElement child); */
NS_IMETHODIMP nsScrollBoxObject::ScrollToElement(nsIDOMElement *child)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void scrollToIndex (in long index); */
NS_IMETHODIMP nsScrollBoxObject::ScrollToIndex(PRInt32 index)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void getPosition (out long x, out long y); */
NS_IMETHODIMP nsScrollBoxObject::GetPosition(PRInt32 *x, PRInt32 *y)
{
nsIScrollableView* scrollableView = GetScrollableView();
if (!scrollableView)
return NS_ERROR_FAILURE;
return scrollableView->GetScrollPosition(*x,*y);
}
/* void getScrolledSize (out long width, out long height); */
NS_IMETHODIMP nsScrollBoxObject::GetScrolledSize(PRInt32 *width, PRInt32 *height)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void ensureElementIsVisible (in nsIDOMElement child); */
NS_IMETHODIMP nsScrollBoxObject::EnsureElementIsVisible(nsIDOMElement *child)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void ensureIndexIsVisible (in long index); */
NS_IMETHODIMP nsScrollBoxObject::EnsureIndexIsVisible(PRInt32 index)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void ensureLineIsVisible (in long line); */
NS_IMETHODIMP nsScrollBoxObject::EnsureLineIsVisible(PRInt32 line)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
nsIScrollableView*
nsScrollBoxObject::GetScrollableView()
{
// get the frame.
nsIFrame* frame = GetFrame();
if (!frame)
return nsnull;
nsCOMPtr<nsIPresContext> context;
mPresShell->GetPresContext(getter_AddRefs(context));
nsIView* view;
frame->GetView(context, &view);
nsIScrollableView* scrollingView = nsnull;
if (NS_SUCCEEDED(view->QueryInterface(kScrollViewIID, (void**)&scrollingView))) {
return scrollingView;
}
return nsnull;
}
nsresult
NS_NewScrollBoxObject(nsIBoxObject** aResult)
{
*aResult = new nsScrollBoxObject;
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}
#if 0
----------------------------------------------
//#define XULTREE
// XXX Hack
#include "nsTreeOuterFrame.h"
class nsTreeBoxObject : public nsITreeBoxObject, public nsBoxObject
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSITREEBOXOBJECT
nsTreeBoxObject();
virtual ~nsTreeBoxObject();
// XXX Will go away as soon as I get off tables.
nsIFrame* GetFrame();
protected:
};
/* Implementation file */
NS_IMPL_ADDREF(nsTreeBoxObject)
NS_IMPL_RELEASE(nsTreeBoxObject)
NS_IMETHODIMP
nsTreeBoxObject::QueryInterface(REFNSIID iid, void** aResult)
{
if (!aResult)
return NS_ERROR_NULL_POINTER;
if (iid.Equals(NS_GET_IID(nsITreeBoxObject))) {
*aResult = (nsITreeBoxObject*)this;
NS_ADDREF(this);
return NS_OK;
}
return nsBoxObject::QueryInterface(iid, aResult);
}
nsTreeBoxObject::nsTreeBoxObject()
{
NS_INIT_ISUPPORTS();
}
nsTreeBoxObject::~nsTreeBoxObject()
{
/* destructor code */
}
// XXX Whole function is a hack that will go away.
nsIFrame*
nsTreeBoxObject::GetFrame()
{
#ifdef XULTREE
return nsBoxObject::GetFrame();
#else
nsIFrame* frame = nsBoxObject::GetFrame();
if (!frame)
return nsnull;
nsTreeOuterFrame* outerFrame = (nsTreeOuterFrame*)frame;
nsCOMPtr<nsIPresContext> presContext;
mPresShell->GetPresContext(getter_AddRefs(presContext));
nsITreeFrame* treeFrame = outerFrame->FindTreeFrame(presContext);
if (!treeFrame)
return nsnull;
return (nsIFrame*)treeFrame;
#endif
}
/* void ensureIndexIsVisible (in long rowIndex); */
NS_IMETHODIMP nsTreeBoxObject::EnsureIndexIsVisible(PRInt32 aRowIndex)
{
nsIFrame* frame = GetFrame();
if (!frame)
return NS_OK;
nsCOMPtr<nsITreeFrame> treeFrame(do_QueryInterface(frame));
return treeFrame->EnsureRowIsVisible(aRowIndex);
}
/* void scrollToIndex (in long rowIndex); */
NS_IMETHODIMP nsTreeBoxObject::ScrollToIndex(PRInt32 aRowIndex)
{
nsIFrame* frame = GetFrame();
if (!frame)
return NS_OK;
nsCOMPtr<nsITreeFrame> treeFrame(do_QueryInterface(frame));
return treeFrame->ScrollToIndex(aRowIndex);
}
/* nsIDOMElement getNextItem (in nsIDOMElement startItem, in long delta); */
NS_IMETHODIMP nsTreeBoxObject::GetNextItem(nsIDOMElement *aStartItem, PRInt32 aDelta, nsIDOMElement **aResult)
{
nsIFrame* frame = GetFrame();
if (!frame)
return NS_OK;
nsCOMPtr<nsITreeFrame> treeFrame(do_QueryInterface(frame));
return treeFrame->GetNextItem(aStartItem, aDelta, aResult);
}
/* nsIDOMElement getPreviousItem (in nsIDOMElement startItem, in long delta); */
NS_IMETHODIMP nsTreeBoxObject::GetPreviousItem(nsIDOMElement *aStartItem, PRInt32 aDelta, nsIDOMElement **aResult)
{
nsIFrame* frame = GetFrame();
if (!frame)
return NS_OK;
nsCOMPtr<nsITreeFrame> treeFrame(do_QueryInterface(frame));
return treeFrame->GetPreviousItem(aStartItem, aDelta, aResult);
}
/* nsIDOMElement getItemAtIndex (in long index); */
NS_IMETHODIMP nsTreeBoxObject::GetItemAtIndex(PRInt32 index, nsIDOMElement **_retval)
{
nsIFrame* frame = GetFrame();
if (!frame)
return NS_OK;
nsCOMPtr<nsITreeFrame> treeFrame(do_QueryInterface(frame));
return treeFrame->GetItemAtIndex(index, _retval);
}
/* long getIndexOfItem (in nsIDOMElement item); */
NS_IMETHODIMP nsTreeBoxObject::GetIndexOfItem(nsIDOMElement* aElement, PRInt32 *aResult)
{
*aResult = -1;
nsIFrame* frame = GetFrame();
if (!frame)
return NS_OK;
nsCOMPtr<nsITreeFrame> treeFrame(do_QueryInterface(frame));
nsCOMPtr<nsIPresContext> presContext;
mPresShell->GetPresContext(getter_AddRefs(presContext));
return treeFrame->GetIndexOfItem(presContext, aElement, aResult);
}
/* void getNumberOfVisibleRows (); */
NS_IMETHODIMP nsTreeBoxObject::GetNumberOfVisibleRows(PRInt32 *aResult)
{
nsIFrame* frame = GetFrame();
if (!frame)
return NS_OK;
nsCOMPtr<nsITreeFrame> treeFrame(do_QueryInterface(frame));
return treeFrame->GetNumberOfVisibleRows(aResult);
}
/* void getIndexOfFirstVisibleRow (); */
NS_IMETHODIMP nsTreeBoxObject::GetIndexOfFirstVisibleRow(PRInt32 *aResult)
{
nsIFrame* frame = GetFrame();
if (!frame)
return NS_OK;
nsCOMPtr<nsITreeFrame> treeFrame(do_QueryInterface(frame));
return treeFrame->GetIndexOfFirstVisibleRow(aResult);
}
// Creation Routine ///////////////////////////////////////////////////////////////////////
nsresult
NS_NewTreeBoxObject(nsIBoxObject** aResult)
{
*aResult = new nsTreeBoxObject;
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}
#endif

Просмотреть файл

@ -207,7 +207,7 @@ nsSprocketLayout::Layout(nsIBox* aBox, nsBoxLayoutState& aState)
x = clientRect.x;
y = clientRect.y;
if (!(frameState & NS_STATE_AUTO_STRETCH)) {
//if (!(frameState & NS_STATE_AUTO_STRETCH)) {
if (frameState & NS_STATE_IS_HORIZONTAL) {
switch(halign) {
case nsBoxFrame::hAlign_Left:
@ -238,7 +238,7 @@ nsSprocketLayout::Layout(nsIBox* aBox, nsBoxLayoutState& aState)
break;
}
}
}
// }
origX = x;
origY = y;
@ -535,7 +535,7 @@ nsSprocketLayout::Layout(nsIBox* aBox, nsBoxLayoutState& aState)
x = clientRect.x;
y = clientRect.y;
if (!(frameState & NS_STATE_AUTO_STRETCH)) {
//if (!(frameState & NS_STATE_AUTO_STRETCH)) {
if (frameState & NS_STATE_IS_HORIZONTAL) {
switch(halign) {
case nsBoxFrame::hAlign_Left:
@ -566,7 +566,7 @@ nsSprocketLayout::Layout(nsIBox* aBox, nsBoxLayoutState& aState)
break;
}
}
}
//}
if (x != origX || y != origY) {
nsIBox* child = nsnull;
@ -596,6 +596,11 @@ nsSprocketLayout::Layout(nsIBox* aBox, nsBoxLayoutState& aState)
void
nsSprocketLayout::PopulateBoxSizes(nsIBox* aBox, nsBoxLayoutState& aState, nsBoxSize*& aBoxSizes, nsComputedBoxSize*& aComputedBoxSizes, nscoord& aMinSize, nscoord& aMaxSize, PRInt32& aFlexes)
{
// used for the equal size flag
nscoord biggestPrefWidth = 0;
nscoord biggestMinWidth = 0;
nscoord smallestMaxWidth = NS_INTRINSICSIZE;
nsFrameState frameState = 0;
GetFrameState(aBox, frameState);
@ -737,11 +742,22 @@ nsSprocketLayout::PopulateBoxSizes(nsIBox* aBox, nsBoxLayoutState& aState, nsBox
else
currentBox->flex = flex;
//currentBox->collapsed = PR_FALSE;
currentBox->pref = prefWidth;
currentBox->min = minWidth;
currentBox->max = maxWidth;
// we we specified all our children are equal size;
if (frameState & NS_STATE_EQUAL_SIZE) {
if (prefWidth > biggestPrefWidth)
biggestPrefWidth = prefWidth;
if (minWidth > biggestMinWidth)
biggestMinWidth = minWidth;
if (maxWidth < smallestMaxWidth)
smallestMaxWidth = maxWidth;
} else { // not we can set our children right now.
currentBox->pref = prefWidth;
currentBox->min = minWidth;
currentBox->max = maxWidth;
}
NS_ASSERTION(minWidth <= prefWidth && prefWidth <= maxWidth,"Bad min, pref, max widths!");
@ -763,6 +779,7 @@ nsSprocketLayout::PopulateBoxSizes(nsIBox* aBox, nsBoxLayoutState& aState, nsBox
}
currentBox->ascent = ascent;
currentBox->collapsed = collapsed;
aFlexes += currentBox->flex;
child->GetNextBox(&child);
@ -771,6 +788,26 @@ nsSprocketLayout::PopulateBoxSizes(nsIBox* aBox, nsBoxLayoutState& aState, nsBox
currentBox = currentBox->next;
}
// we we specified all our children are equal size;
if (frameState & NS_STATE_EQUAL_SIZE) {
currentBox = aBoxSizes;
while(currentBox)
{
if (!currentBox->collapsed) {
currentBox->pref = biggestPrefWidth;
currentBox->min = biggestMinWidth;
currentBox->max = smallestMaxWidth;
} else {
currentBox->pref = 0;
currentBox->min = 0;
currentBox->max = 0;
}
currentBox = currentBox->next;
}
}
}
void
@ -1133,7 +1170,9 @@ nsSprocketLayout::ComputeChildSizes(nsIBox* aBox,
NS_IMETHODIMP
nsSprocketLayout::GetPrefSize(nsIBox* aBox, nsBoxLayoutState& aState, nsSize& aSize)
{
PRBool isHorizontal = IsHorizontal(aBox);
PRBool isHorizontal = IsHorizontal(aBox);
nscoord biggestPref = 0;
aSize.width = 0;
aSize.height = 0;
@ -1143,24 +1182,49 @@ nsSprocketLayout::GetPrefSize(nsIBox* aBox, nsBoxLayoutState& aState, nsSize& aS
nsIBox* child = nsnull;
aBox->GetChildBox(&child);
nsFrameState frameState = 0;
GetFrameState(aBox, frameState);
PRBool isEqual = frameState & NS_STATE_EQUAL_SIZE;
PRInt32 count = 0;
while (child)
{
// ignore collapsed children
//PRBool isCollapsed = PR_FALSE;
//child->IsCollapsed(aState, isCollapsed);
PRBool isCollapsed = PR_FALSE;
child->IsCollapsed(aState, isCollapsed);
//if (!isCollapsed)
//{
if (!isCollapsed)
{
nsSize pref(0,0);
child->GetPrefSize(aState, pref);
AddMargin(child, pref);
if (isEqual) {
if (isHorizontal)
{
if (pref.width > biggestPref)
biggestPref = pref.width;
} else {
if (pref.height > biggestPref)
biggestPref = pref.height;
}
}
AddLargestSize(aSize, pref, isHorizontal);
//}
count++;
}
child->GetNextBox(&child);
}
if (isEqual) {
if (isHorizontal)
aSize.width = biggestPref*count;
else
aSize.height = biggestPref*count;
}
// now add our border and padding and insets
AddBorderAndPadding(aBox, aSize);
AddInset(aBox, aSize);
@ -1171,8 +1235,9 @@ nsSprocketLayout::GetPrefSize(nsIBox* aBox, nsBoxLayoutState& aState, nsSize& aS
NS_IMETHODIMP
nsSprocketLayout::GetMinSize(nsIBox* aBox, nsBoxLayoutState& aState, nsSize& aSize)
{
PRBool isHorizontal = IsHorizontal(aBox);
PRBool isHorizontal = IsHorizontal(aBox);
nscoord biggestMin = 0;
aSize.width = 0;
aSize.height = 0;
@ -1182,15 +1247,19 @@ nsSprocketLayout::GetMinSize(nsIBox* aBox, nsBoxLayoutState& aState, nsSize& aSi
nsIBox* child = nsnull;
aBox->GetChildBox(&child);
nsFrameState frameState = 0;
GetFrameState(aBox, frameState);
PRBool isEqual = frameState & NS_STATE_EQUAL_SIZE;
PRInt32 count = 0;
while (child)
{
// ignore collapsed children
//PRBool isCollapsed = PR_FALSE;
//aBox->IsCollapsed(aState, isCollapsed);
PRBool isCollapsed = PR_FALSE;
aBox->IsCollapsed(aState, isCollapsed);
//if (!isCollapsed)
//{
if (!isCollapsed)
{
nsSize min(0,0);
nsSize pref(0,0);
nscoord flex = 0;
@ -1208,13 +1277,33 @@ nsSprocketLayout::GetMinSize(nsIBox* aBox, nsBoxLayoutState& aState, nsSize& aSi
min.height = pref.height;
}
if (isEqual) {
if (isHorizontal)
{
if (min.width > biggestMin)
biggestMin = min.width;
} else {
if (min.height > biggestMin)
biggestMin = min.height;
}
}
AddMargin(child, min);
AddLargestSize(aSize, min, isHorizontal);
//}
count++;
}
child->GetNextBox(&child);
}
if (isEqual) {
if (isHorizontal)
aSize.width = biggestMin*count;
else
aSize.height = biggestMin*count;
}
// now add our border and padding and insets
AddBorderAndPadding(aBox, aSize);
AddInset(aBox,aSize);
@ -1228,6 +1317,7 @@ nsSprocketLayout::GetMaxSize(nsIBox* aBox, nsBoxLayoutState& aState, nsSize& aSi
PRBool isHorizontal = IsHorizontal(aBox);
nscoord smallestMax = NS_INTRINSICSIZE;
aSize.width = NS_INTRINSICSIZE;
aSize.height = NS_INTRINSICSIZE;
@ -1238,25 +1328,54 @@ nsSprocketLayout::GetMaxSize(nsIBox* aBox, nsBoxLayoutState& aState, nsSize& aSi
nsIBox* child = nsnull;
aBox->GetChildBox(&child);
nsFrameState frameState = 0;
GetFrameState(aBox, frameState);
PRBool isEqual = frameState & NS_STATE_EQUAL_SIZE;
PRInt32 count = 0;
while (child)
{
// ignore collapsed children
//PRBool isCollapsed = PR_FALSE;
//aBox->IsCollapsed(aState, isCollapsed);
PRBool isCollapsed = PR_FALSE;
aBox->IsCollapsed(aState, isCollapsed);
//if (!isCollapsed)
//{
if (!isCollapsed)
{
// if completely redefined don't even ask our child for its size.
nsSize max(NS_INTRINSICSIZE, NS_INTRINSICSIZE);
child->GetMaxSize(aState, max);
AddMargin(child, max);
AddSmallestSize(aSize, max, isHorizontal);
//}
child->GetNextBox(&child);
if (isEqual) {
if (isHorizontal)
{
if (max.width < smallestMax)
smallestMax = max.width;
} else {
if (max.height < smallestMax)
smallestMax = max.height;
}
}
count++;
}
child->GetNextBox(&child);
}
if (isEqual) {
if (isHorizontal) {
if (smallestMax != NS_INTRINSICSIZE)
aSize.width = smallestMax*count;
else
aSize.width = NS_INTRINSICSIZE;
} else {
if (smallestMax != NS_INTRINSICSIZE)
aSize.height = smallestMax*count;
else
aSize.height = NS_INTRINSICSIZE;
}
}
// now add our border and padding and insets
@ -1474,7 +1593,7 @@ nsBoxSize::Clear()
pref = 0;
min = 0;
max = NS_INTRINSICSIZE;
//collapsed = PR_FALSE;
collapsed = PR_FALSE;
ascent = 0;
left = 0;
right = 0;

Просмотреть файл

@ -42,7 +42,7 @@ public:
nscoord flex;
nscoord left;
nscoord right;
//PRBool collapsed;
PRBool collapsed;
PRBool bogus;
nsBoxSize* next;

Просмотреть файл

@ -98,13 +98,19 @@ XUL_ATOM(titledbutton, "titledbutton")
XUL_ATOM(crop, "crop")
XUL_ATOM(mode, "mode")
XUL_ATOM(equalsize, "equalsize")
XUL_ATOM(box, "box")
XUL_ATOM(hbox, "hbox")
XUL_ATOM(vbox, "vbox")
XUL_ATOM(scrollbox, "scrollbox")
XUL_ATOM(mousethrough, "mousethrough")
XUL_ATOM(flex, "flex")
XUL_ATOM(spring, "spring")
XUL_ATOM(orient, "orient")
XUL_ATOM(autostretch, "autostretch")
XUL_ATOM(autorepeatbutton, "autorepeatbutton")
XUL_ATOM(titledbox, "titledbox")
XUL_ATOM(title, "title")
XUL_ATOM(titledboxContentPseudo, ":titledbox-content")

Просмотреть файл

@ -84,3 +84,4 @@ NS_XULATOM(value);
NS_XULATOM(width);
NS_XULATOM(window);
NS_XULATOM(xulcontentsgenerated);
NS_XULATOM(scrollbox);

Просмотреть файл

@ -218,6 +218,8 @@ nsXULContentUtils::kEventHandlerMap[] = {
{ "oncommand", nsnull, &NS_GET_IID(nsIDOMMenuListener) },
{ "onbroadcast", nsnull, &NS_GET_IID(nsIDOMMenuListener) },
{ "oncommandupdate", nsnull, &NS_GET_IID(nsIDOMMenuListener) },
{ "onoverflow", nsnull, &NS_GET_IID(nsIDOMMenuListener) },
{ "onunderflow", nsnull, &NS_GET_IID(nsIDOMMenuListener) },
{ "onfocus", nsnull, &NS_GET_IID(nsIDOMFocusListener) },
{ "onblur", nsnull, &NS_GET_IID(nsIDOMFocusListener) },

Просмотреть файл

@ -344,6 +344,7 @@ nsXULElement::Init()
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF service");
if (NS_FAILED(rv)) return rv;
rv = nsComponentManager::CreateInstance(kNameSpaceManagerCID,
nsnull,
kINameSpaceManagerIID,
@ -397,6 +398,7 @@ nsXULElement::~nsXULElement()
gRDFService = nsnull;
}
NS_IF_RELEASE(gNameSpaceManager);
if (gXULUtils) {
@ -4035,6 +4037,9 @@ nsXULElement::GetBoxObject(nsIBoxObject** aResult)
progID += "-popupset";
else if (tag.get() == nsXULAtoms::tree)
progID += "-tree";
else if (tag.get() == nsXULAtoms::scrollbox)
progID += "-scrollbox";
mBoxObject = do_CreateInstance(progID);
if (!mBoxObject)

Просмотреть файл

@ -330,6 +330,7 @@ protected:
static PRInt32 kNameSpaceID_RDF;
static PRInt32 kNameSpaceID_XUL;
public:
static nsresult
Create(nsXULPrototypeElement* aPrototype, nsIDocument* aDocument, PRBool aIsScriptable, nsIContent** aResult);

Просмотреть файл

@ -183,6 +183,28 @@ menuitem[checked="true"][menuactive="true"]
padding : 3px;
}
/*
* Autorepeatbutton
*/
.autorepeatbutton-up {
list-style-image: url("chrome://global/skin/scroll-up.gif")
}
.autorepeatbutton-down {
list-style-image: url("chrome://global/skin/scroll-down.gif")
}
autorepeatbutton {
text-align: center;
vertical-align: middle;
}
autorepeatbutton:hover {
background-color : #336699;
}

Просмотреть файл

@ -186,6 +186,30 @@ menuitem[checked="true"][disabled="true"]
font : smaller;
padding : 3px;
}
/*
* Autorepeatbutton
*/
.autorepeatbutton-up {
list-style-image: url("chrome://global/skin/scroll-up.gif")
}
.autorepeatbutton-down {
list-style-image: url("chrome://global/skin/scroll-down.gif")
}
autorepeatbutton {
text-align: center;
vertical-align: middle;
}
autorepeatbutton:hover {
background-color: highlight;
}

Просмотреть файл

@ -186,6 +186,30 @@ menuitem[checked="true"][disabled="true"]
font : smaller;
padding : 3px;
}
/*
* Autorepeatbutton
*/
.autorepeatbutton-up {
list-style-image: url("chrome://global/skin/scroll-up.gif")
}
.autorepeatbutton-down {
list-style-image: url("chrome://global/skin/scroll-down.gif")
}
autorepeatbutton {
text-align: center;
vertical-align: middle;
}
autorepeatbutton:hover {
background-color : highlight;
}

Просмотреть файл

@ -185,6 +185,29 @@ menuitem[checked="true"][menuactive="true"]
font : smaller;
padding : 3px;
}
/*
* Autorepeatbutton
*/
.autorepeatbutton-up {
list-style-image: url("chrome://global/skin/scroll-up.gif")
}
.autorepeatbutton-down {
list-style-image: url("chrome://global/skin/scroll-down.gif")
}
autorepeatbutton {
text-align: center;
vertical-align: middle;
}
autorepeatbutton:hover {
background-color: #336699;
}

Просмотреть файл

@ -151,6 +151,15 @@ struct nsScrollbarEvent : public nsGUIEvent {
PRUint32 position;
};
struct nsScrollPortEvent : public nsGUIEvent {
enum orientType {
vertical = 0,
horizontal = 1,
both = 2
};
orientType orient;
};
struct nsInputEvent : public nsGUIEvent {
/// PR_TRUE indicates the shift key is down
@ -278,8 +287,8 @@ enum nsDragDropEventStatus {
#define NS_COMPOSITION_END 15
#define NS_MOUSE_SCROLL_EVENT 16
#define NS_COMPOSITION_QUERY 17
#define NS_SCROLLPORT_EVENT 18
/**
* GUI MESSAGES
*/
@ -411,6 +420,10 @@ enum nsDragDropEventStatus {
#define NS_MOUSE_SCROLL_START 1600
#define NS_MOUSE_SCROLL (NS_MOUSE_SCROLL_START)
#define NS_SCROLLPORT_START 1700
#define NS_SCROLLPORT_UNDERFLOW (NS_SCROLLPORT_START)
#define NS_SCROLLPORT_OVERFLOW (NS_SCROLLPORT_START+1)
#define NS_IS_MOUSE_EVENT(evnt) \
(((evnt)->message == NS_MOUSE_LEFT_BUTTON_DOWN) || \
((evnt)->message == NS_MOUSE_LEFT_BUTTON_UP) || \

Просмотреть файл

@ -99,16 +99,26 @@ iframe {
behavior: url(chrome://global/content/xulBindings.xml#iframe);
}
/******** ScrollBox ********/
scrollbox {
behavior: url(chrome://global/content/xulBindings.xml#scrollbox);
}
.scrollbox-innerbox {
text-align: inherit;
vertical-align: inherit;
}
/******** ArrowScrollBox ******/
arrowscrollbox {
behavior: url(chrome://global/content/xulBindings.xml#arrowscrollbox);
}
/******** Box *******/
hbox {
behavior: url(chrome://global/content/xulBindings.xml#hbox);
}
vbox {
behavior: url(chrome://global/content/xulBindings.xml#vbox);
}
/******** TitledBox *******/
box.titledbox-title {
@ -553,4 +563,19 @@ statusbarpanel
{
user-focus : ignore;
behavior : url("chrome://global/content/xulBindings.xml#statusbar-panel");
}
}
/**
* AutoRepeater
*/
autorepeater {
user-focus : ignore;
}
autorepeatbutton.up {
behavior : url("chrome://global/content/xulBindings.xml#autorepeatbutton-up");
}
autorepeatbutton.down {
behavior : url("chrome://global/content/xulBindings.xml#autorepeatbutton-down");
}

Просмотреть файл

@ -5,12 +5,6 @@
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<binding id="hbox" extends="xul:box"/>
<binding id="vbox" extends="xul:box">
<content orient="vertical"/>
</binding>
<binding id="thumb" extends="xul:box">
<content>
<xul:spring flex="1"/>
@ -308,9 +302,16 @@
<binding id="popups">
<content>
<xul:box class="popup-internal-box" orient="vertical" flex="1" style="overflow: auto">
<!--xul:box class="popup-internal-box" orient="vertical" flex="1" style="overflow: auto">
<children/>
</xul:box>
</xul:box-->
<xul:arrowscrollbox flex="1" orient="vertical">
<!--xul:box class="popup-internal-box" orient="vertical"-->
<children/>
<!--/xul:box-->
</xul:arrowscrollbox>
</content>
<interface>
<method name="openPopup">
@ -582,5 +583,51 @@
</content>
</binding>
<binding id="autorepeatbutton-up">
<content>
<xul:image class="autorepeatbutton-up"/>
</content>
</binding>
<binding id="autorepeatbutton-down">
<content>
<xul:image class="autorepeatbutton-down"/>
</content>
</binding>
<binding id="scrollbox">
<content>
<xul:box class="scrollbox-innerbox" inherits="orient,autostretch,align,valign">
<children/>
</xul:box>
</content>
</binding>
<binding id="arrowscrollbox" extends="xul:stack">
<content>
<xul:vbox
onunderflow="
var button1 = this.firstChild;
var button2 = this.childNodes[2];
button1.setAttribute('collapsed', 'true');
button2.setAttribute('collapsed', 'true');
"
onoverflow="
var button1 = this.firstChild;
var button2 = this.childNodes[2];
button1.removeAttribute('collapsed');
button2.removeAttribute('collapsed');
">
<xul:autorepeatbutton autostretch="never" class="up" collapsed="true"
oncommand="parentNode.childNodes[1].boxObject.QueryInterface(Components.interfaces.nsIScrollBoxObject).scrollByIndex(-1);"/>
<xul:scrollbox orient="vertical" flex="1">
<children/>
</xul:scrollbox>
<xul:autorepeatbutton autostretch="never" class="down" collapsed="true"
oncommand="parentNode.childNodes[1].boxObject.QueryInterface(Components.interfaces.nsIScrollBoxObject).scrollByIndex(1);"/>
</xul:vbox>
</content>
</binding>
</bindings>