Files
Mozilla/mozilla/widget/src/mac/nsComboBox.cpp
pierre%netscape.com 19ae9087ee Fixed various problems with popups (fixed width, empty strings, strings starting with '-'). Simplified some functions too.
git-svn-id: svn://10.0.0.236/trunk@33520 18797224-902f-48f8-a5cc-f745e15eee43
1999-06-03 08:38:52 +00:00

356 lines
9.3 KiB
C++

/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsComboBox.h"
#include "nsMenu.h"
#include <StringCompare.h>
#if TARGET_CARBON
#include <ControlDefinitions.h>
#endif
NS_IMPL_ADDREF(nsComboBox);
NS_IMPL_RELEASE(nsComboBox);
#define DASH '-'
#define OPTION_DASH 'Ð'
//-------------------------------------------------------------------------
//
// nsComboBox constructor
//
//-------------------------------------------------------------------------
nsComboBox::nsComboBox() : nsMacControl(), nsIListWidget(), nsIComboBox()
{
NS_INIT_REFCNT();
strcpy(gInstanceClassName, "nsComboBox");
SetControlType(kControlPopupButtonProc + kControlPopupFixedWidthVariant);
mMenuHandle = nsnull;
mMenuID = -12345; // so that the control doesn't look for a menu in resource
mMin = mMenuID; // when creating a popup, 'min' must contain the menuID
}
//-------------------------------------------------------------------------
//
// nsComboBox:: destructor
//
//-------------------------------------------------------------------------
nsComboBox::~nsComboBox()
{
if (mMenuHandle)
{
// ::DeleteMenu(mMenuID);
// ::DisposeMenu(mMenuHandle);
mMenuHandle = nsnull;
}
}
//-------------------------------------------------------------------------
//
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsComboBox::Create(nsIWidget *aParent,
const nsRect &aRect,
EVENT_CALLBACK aHandleEventFunction,
nsIDeviceContext *aContext,
nsIAppShell *aAppShell,
nsIToolkit *aToolkit,
nsWidgetInitData *aInitData)
{
nsresult res = Inherited::Create(aParent, aRect, aHandleEventFunction,
aContext, aAppShell, aToolkit, aInitData);
if (res == NS_OK)
{
mMenuID = nsMenu::GetUniqueMenuID();
mMenuHandle = ::NewMenu(mMenuID, "\p");
if (mMenuHandle)
{
StartDraw();
::InsertMenu(mMenuHandle, hierMenu);
// ::SetControlData(mControl, kControlNoPart, kControlPopupButtonMenuHandleTag, sizeof(mMenuHandle), (Ptr)&mMenuHandle);
// ::SetControlData(mControl, kControlNoPart, kControlPopupButtonMenuIDTag, sizeof(mMenuID), (Ptr)&mMenuID);
#if TARGET_CARBON
::SetControlPopupMenuHandle ( mControl, mMenuHandle );
::SetControlPopupMenuID ( mControl, mMenuID );
#else
PopupPrivateData* popupData = (PopupPrivateData*)*((*mControl)->contrlData);
if (popupData)
{
popupData->mHandle = mMenuHandle;
popupData->mID = mMenuID;
}
#endif
EndDraw();
}
else
res = NS_ERROR_FAILURE;
}
return res;
}
//-------------------------------------------------------------------------
//
//
//-------------------------------------------------------------------------
nsresult nsComboBox::QueryInterface(const nsIID& aIID, void** aInstancePtr)
{
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
static NS_DEFINE_IID(kInsComboBoxIID, NS_ICOMBOBOX_IID);
static NS_DEFINE_IID(kInsListWidgetIID, NS_ILISTWIDGET_IID);
if (aIID.Equals(kInsComboBoxIID)) {
*aInstancePtr = (void*) ((nsIComboBox*)this);
NS_ADDREF_THIS();
return NS_OK;
}
else if (aIID.Equals(kInsListWidgetIID)) {
*aInstancePtr = (void*) ((nsIListWidget*)this);
NS_ADDREF_THIS();
return NS_OK;
}
return nsWindow::QueryInterface(aIID,aInstancePtr);
}
#pragma mark -
//-------------------------------------------------------------------------
//
// AddItemAt
//
//-------------------------------------------------------------------------
nsresult nsComboBox::AddItemAt(nsString &aItem, PRInt32 aPosition)
{
if (! mMenuHandle)
return NS_ERROR_NOT_INITIALIZED;
Str255 pString;
StringToStr255(aItem, pString);
// Mac hacks: a menu item should not be an empty string
// (otherwise a new item is not appended to the menu)
// and it should not contain a dash '-' as first character
// (otherwise it is considered as a menu separator even though
// we are doing a 2-step initialization with MacInsertMenuItem()
// and SetMenuItemText()).
if (pString[0] == 0)
{
pString[0] = 1;
pString[1] = ' ';
}
else if (pString[1] == DASH) {
pString[1] = OPTION_DASH;
}
StartDraw();
short menuItems = GetItemCount();
if (aPosition == -1 || aPosition > menuItems) {
aPosition = menuItems;
}
::MacInsertMenuItem(mMenuHandle, "\p ", aPosition);
::SetMenuItemText(mMenuHandle, aPosition + 1, pString);
menuItems = GetItemCount();
::SetControlMinimum(mControl, (menuItems ? 1 : 0));
::SetControlMaximum(mControl, (menuItems ? menuItems : 0));
EndDraw();
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Finds an item at a postion
//
//-------------------------------------------------------------------------
PRInt32 nsComboBox::FindItem(nsString &aItem, PRInt32 aStartPos)
{
if (! mMenuHandle)
return -1;
PRInt32 index = -1;
short itemCount = GetItemCount();
for (short i = aStartPos; i < itemCount; i ++)
{
nsString temp;
GetItemAt(temp, i);
if (aItem == temp)
{
index = i;
break;
}
}
return index;
}
//-------------------------------------------------------------------------
//
// CountItems - Get Item Count
//
//-------------------------------------------------------------------------
PRInt32 nsComboBox::GetItemCount()
{
if (! mMenuHandle)
return 0;
return ::CountMenuItems(mMenuHandle);
}
//-------------------------------------------------------------------------
//
// Removes an Item at a specified location
//
//-------------------------------------------------------------------------
PRBool nsComboBox::RemoveItemAt(PRInt32 aPosition)
{
if (! mMenuHandle)
return PR_FALSE;
if (GetItemCount() < aPosition)
return PR_FALSE;
StartDraw();
if (aPosition == -1)
::DeleteMenuItem(mMenuHandle, GetItemCount());
else
::DeleteMenuItem(mMenuHandle, aPosition + 1);
short menuItems = GetItemCount();
::SetControlMinimum(mControl, (menuItems ? 1 : 0));
::SetControlMaximum(mControl, (menuItems ? menuItems : 0));
EndDraw();
return PR_TRUE;
}
//-------------------------------------------------------------------------
//
// Returns an Item at a specified location
//
//-------------------------------------------------------------------------
PRBool nsComboBox::GetItemAt(nsString& anItem, PRInt32 aPosition)
{
anItem = "";
if (! mMenuHandle)
return PR_FALSE;
if (aPosition >= GetItemCount())
return PR_FALSE;
Str255 itemStr;
::GetMenuItemText(mMenuHandle, aPosition + 1, itemStr);
if (itemStr[1] == OPTION_DASH) // see AddItemAt() for more info
itemStr[1] = DASH;
Str255ToString(itemStr, anItem);
return PR_TRUE;
}
//-------------------------------------------------------------------------
//
// Gets the selected of selected item
//
//-------------------------------------------------------------------------
nsresult nsComboBox::GetSelectedItem(nsString& anItem)
{
return GetItemAt(anItem, GetSelectedIndex());
}
//-------------------------------------------------------------------------
//
// Gets the list of selected otems
//
//-------------------------------------------------------------------------
PRInt32 nsComboBox::GetSelectedIndex()
{
if (! mMenuHandle)
return -1;
return ::GetControlValue(mControl) - 1;
}
//-------------------------------------------------------------------------
//
// SelectItem
//
//-------------------------------------------------------------------------
nsresult nsComboBox::SelectItem(PRInt32 aPosition)
{
if (! mMenuHandle)
return NS_ERROR_NOT_INITIALIZED;
StartDraw();
if (aPosition == -1)
::SetControlValue(mControl, GetItemCount());
else
::SetControlValue(mControl, aPosition + 1);
EndDraw();
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Deselect
//
//-------------------------------------------------------------------------
nsresult nsComboBox::Deselect()
{
return SelectItem(0);
}
//-------------------------------------------------------------------------
//
// DispatchMouseEvent
//
//-------------------------------------------------------------------------
PRBool nsComboBox::DispatchMouseEvent(nsMouseEvent &aEvent)
{
PRBool eatEvent = PR_FALSE;
switch (aEvent.message)
{
case NS_MOUSE_LEFT_DOUBLECLICK:
case NS_MOUSE_LEFT_BUTTON_DOWN:
StartDraw();
{
Point thePoint;
thePoint.h = aEvent.point.x;
thePoint.v = aEvent.point.y;
::TrackControl(mControl, thePoint, nil);
//¥TODO: the mouseUp event is eaten by TrackControl.
//¥ We must create it and dispatch it after the mouseDown;
eatEvent = PR_TRUE;
}
EndDraw();
break;
}
if (eatEvent)
return PR_TRUE;
return (Inherited::DispatchMouseEvent(aEvent));
}