Back to index

lightning-sunbird  0.9+nobinonly
nsScrollbarButtonFrame.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla Communicator client code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 //
00039 // Eric Vaughan
00040 // Netscape Communications
00041 //
00042 // See documentation in associated header file
00043 //
00044 
00045 #include "nsScrollbarButtonFrame.h"
00046 #include "nsPresContext.h"
00047 #include "nsIContent.h"
00048 #include "nsCOMPtr.h"
00049 #include "nsUnitConversion.h"
00050 #include "nsINameSpaceManager.h"
00051 #include "nsHTMLAtoms.h"
00052 #include "nsXULAtoms.h"
00053 #include "nsSliderFrame.h"
00054 #include "nsIScrollbarFrame.h"
00055 #include "nsIScrollbarMediator.h"
00056 #include "nsRepeatService.h"
00057 #include "nsGUIEvent.h"
00058 
00059 //
00060 // NS_NewToolbarFrame
00061 //
00062 // Creates a new Toolbar frame and returns it in |aNewFrame|
00063 //
00064 nsresult
00065 NS_NewScrollbarButtonFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame )
00066 {
00067   NS_PRECONDITION(aNewFrame, "null OUT ptr");
00068   if (nsnull == aNewFrame) {
00069     return NS_ERROR_NULL_POINTER;
00070   }
00071   nsScrollbarButtonFrame* it = new (aPresShell) nsScrollbarButtonFrame (aPresShell);
00072   if (nsnull == it)
00073     return NS_ERROR_OUT_OF_MEMORY;
00074 
00075   *aNewFrame = it;
00076   return NS_OK;
00077   
00078 } // NS_NewScrollBarButtonFrame
00079 
00080 
00081 nsScrollbarButtonFrame::nsScrollbarButtonFrame(nsIPresShell* aPresShell)
00082 :nsButtonBoxFrame(aPresShell)
00083 {
00084 }
00085 
00086 
00087 
00088 NS_IMETHODIMP 
00089 nsScrollbarButtonFrame::QueryInterface(REFNSIID aIID, void** aInstancePtr)      
00090 {           
00091   if (aIID.Equals(NS_GET_IID(nsITimerCallback))) {                                         
00092     *aInstancePtr = (void*)(nsITimerCallback*) this;                                        
00093     NS_ADDREF_THIS();                                                    
00094     return NS_OK;                                                        
00095   }   
00096 
00097   return nsButtonBoxFrame::QueryInterface(aIID, aInstancePtr);                                     
00098 }
00099 
00100 NS_IMETHODIMP
00101 nsScrollbarButtonFrame::HandleEvent(nsPresContext* aPresContext, 
00102                                     nsGUIEvent* aEvent,
00103                                     nsEventStatus* aEventStatus)
00104 {  
00105   // XXX hack until handle release is actually called in nsframe.
00106   if (aEvent->message == NS_MOUSE_EXIT_SYNTH|| aEvent->message == NS_MOUSE_RIGHT_BUTTON_UP || aEvent->message == NS_MOUSE_LEFT_BUTTON_UP)
00107      HandleRelease(aPresContext, aEvent, aEventStatus);
00108   
00109   return nsButtonBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
00110 }
00111 
00112 
00113 NS_IMETHODIMP
00114 nsScrollbarButtonFrame::HandlePress(nsPresContext* aPresContext, 
00115                                     nsGUIEvent*     aEvent,
00116                                     nsEventStatus*  aEventStatus)
00117 {
00118   MouseClicked();
00119   nsRepeatService::GetInstance()->Start(this);
00120   return NS_OK;
00121 }
00122 
00123 NS_IMETHODIMP 
00124 nsScrollbarButtonFrame::HandleRelease(nsPresContext* aPresContext, 
00125                                       nsGUIEvent*     aEvent,
00126                                       nsEventStatus*  aEventStatus)
00127 {
00128   nsRepeatService::GetInstance()->Stop();
00129   return NS_OK;
00130 }
00131 
00132 
00133 NS_IMETHODIMP nsScrollbarButtonFrame::Notify(nsITimer *timer)
00134 {
00135   MouseClicked();
00136   return NS_OK;
00137 }
00138 
00139 void
00140 nsScrollbarButtonFrame::MouseClicked(nsPresContext* aPresContext, nsGUIEvent* aEvent) 
00141 {
00142   nsButtonBoxFrame::MouseClicked(aPresContext, aEvent);
00143   //MouseClicked();
00144 }
00145 
00146 void
00147 nsScrollbarButtonFrame::MouseClicked() 
00148 {
00149    // when we are clicked either increment or decrement the slider position.
00150 
00151    // get the scrollbar control
00152    nsIFrame* scrollbar;
00153    GetParentWithTag(nsXULAtoms::scrollbar, this, scrollbar);
00154 
00155    if (scrollbar == nsnull)
00156        return;
00157 
00158    // get the scrollbars content node
00159    nsCOMPtr<nsIContent> content = scrollbar->GetContent();
00160 
00161    // get the current pos
00162    PRInt32 curpos = nsSliderFrame::GetCurrentPosition(content);
00163    PRInt32 oldpos = curpos;
00164 
00165    // get the max pos
00166    PRInt32 maxpos = nsSliderFrame::GetMaxPosition(content);
00167 
00168    // get the increment amount
00169    PRInt32 increment = nsSliderFrame::GetIncrement(content);
00170 #ifdef MOZ_WIDGET_COCOA
00171    // Emulate the Mac IE behavior of scrolling 2 lines instead of 1
00172    // on a button press.  This makes scrolling appear smoother and
00173    // keeps us competitive with IE.
00174    increment *= 2;
00175 #endif
00176 
00177    nsString value;
00178    if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttr(kNameSpaceID_None, nsHTMLAtoms::type, value))
00179    {
00180      // if our class is DecrementButton subtract the current pos by increment amount
00181      // if our class is IncrementButton increment the current pos by the decrement amount
00182      if (value.EqualsLiteral("decrement"))
00183          curpos -= increment;
00184      else if (value.EqualsLiteral("increment"))
00185          curpos += increment;
00186 
00187       // make sure the current positon is between the current and max positions
00188     if (curpos < 0)
00189        curpos = 0;
00190     else if (curpos > maxpos)
00191        curpos = maxpos;
00192 
00193     nsCOMPtr<nsIScrollbarFrame> sb(do_QueryInterface(scrollbar));
00194     if (sb) {
00195       nsCOMPtr<nsIScrollbarMediator> m;
00196       sb->GetScrollbarMediator(getter_AddRefs(m));
00197       if (m) {
00198         m->ScrollbarButtonPressed(sb, oldpos, curpos);
00199         return;
00200       }
00201     }
00202 
00203     // set the current position of the slider.
00204     nsAutoString curposStr;
00205     curposStr.AppendInt(curpos);
00206 
00207     content->SetAttr(kNameSpaceID_None, nsXULAtoms::smooth, NS_LITERAL_STRING("true"), PR_FALSE);
00208     content->SetAttr(kNameSpaceID_None, nsXULAtoms::curpos, curposStr, PR_TRUE);
00209     content->UnsetAttr(kNameSpaceID_None, nsXULAtoms::smooth, PR_FALSE);
00210   }
00211 }
00212 
00213 nsresult
00214 nsScrollbarButtonFrame::GetChildWithTag(nsPresContext* aPresContext,
00215                                         nsIAtom* atom, nsIFrame* start,
00216                                         nsIFrame*& result)
00217 {
00218   // recursively search our children
00219   nsIFrame* childFrame = start->GetFirstChild(nsnull);
00220   while (nsnull != childFrame) 
00221   {    
00222     // get the content node
00223     nsIContent* child = childFrame->GetContent();
00224 
00225     if (child) {
00226       // see if it is the child
00227        if (child->Tag() == atom)
00228        {
00229          result = childFrame;
00230 
00231          return NS_OK;
00232        }
00233     }
00234 
00235      // recursive search the child
00236      GetChildWithTag(aPresContext, atom, childFrame, result);
00237      if (result != nsnull) 
00238        return NS_OK;
00239 
00240     childFrame = childFrame->GetNextSibling();
00241   }
00242 
00243   result = nsnull;
00244   return NS_OK;
00245 }
00246 
00247 nsresult
00248 nsScrollbarButtonFrame::GetParentWithTag(nsIAtom* toFind, nsIFrame* start,
00249                                          nsIFrame*& result)
00250 {
00251    while (start)
00252    {
00253       start = start->GetParent();
00254 
00255       if (start) {
00256         // get the content node
00257         nsIContent* child = start->GetContent();
00258 
00259         if (child && child->Tag() == toFind) {
00260           result = start;
00261           return NS_OK;
00262         }
00263       }
00264    }
00265 
00266    result = nsnull;
00267    return NS_OK;
00268 }
00269 
00270 NS_IMETHODIMP
00271 nsScrollbarButtonFrame::Destroy(nsPresContext* aPresContext)
00272 {
00273   // Ensure our repeat service isn't going... it's possible that a scrollbar can disappear out
00274   // from under you while you're in the process of scrolling.
00275   nsRepeatService::GetInstance()->Stop();
00276   return nsButtonBoxFrame::Destroy(aPresContext);
00277 }