391 lines
9.9 KiB
C++
391 lines
9.9 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 "nsRadioGroup.h"
|
|
#include "nsToolkit.h"
|
|
#include "nsStringUtil.h"
|
|
|
|
|
|
class nsStringHashKey : public nsHashKey {
|
|
public:
|
|
nsStringHashKey(const nsString & aKey);
|
|
~nsStringHashKey();
|
|
|
|
PRBool operator==(const nsStringHashKey& aOther) const;
|
|
PRBool Equals(const nsHashKey* aOther) const;
|
|
PRUint32 HashValue(void) const;
|
|
nsHashKey* Clone(void) const;
|
|
|
|
private:
|
|
nsStringHashKey();
|
|
nsStringHashKey(const nsStringHashKey& aCopy);
|
|
nsStringHashKey& operator=(const nsStringHashKey& aCopy);
|
|
|
|
protected:
|
|
nsString mKey;
|
|
PRUint32 mHashValid;
|
|
PRUint32 mHashValue;
|
|
|
|
};
|
|
|
|
nsStringHashKey::nsStringHashKey(const nsString & aKey)
|
|
{
|
|
mKey.SetLength(0);
|
|
mKey.Append(aKey);
|
|
mHashValid = 0;
|
|
}
|
|
|
|
nsStringHashKey::nsStringHashKey(const nsStringHashKey& aCopy)
|
|
{
|
|
mKey.SetLength(0);
|
|
mKey.Append(aCopy.mKey);
|
|
mHashValid = aCopy.mHashValid;
|
|
mHashValue = aCopy.mHashValue;
|
|
}
|
|
|
|
nsStringHashKey::~nsStringHashKey()
|
|
{
|
|
}
|
|
|
|
PRBool nsStringHashKey::operator==(const nsStringHashKey& aOther) const
|
|
{
|
|
return Equals(&aOther);
|
|
}
|
|
|
|
PRBool nsStringHashKey::Equals(const nsHashKey* aOther) const
|
|
{
|
|
PRBool result = PR_TRUE;
|
|
|
|
const nsStringHashKey* other = (nsStringHashKey*)aOther;
|
|
|
|
if (nsnull != other && other != this) {
|
|
result = mKey.Equals(other->mKey);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
nsHashKey* nsStringHashKey::Clone(void) const
|
|
{
|
|
return new nsStringHashKey(*this);
|
|
}
|
|
|
|
PRUint32 nsStringHashKey::HashValue(void) const
|
|
{
|
|
if (0 == mHashValid) {
|
|
((nsStringHashKey*)this)->mHashValue = 0;
|
|
|
|
NS_ALLOC_STR_BUF(val, mKey, 256)
|
|
PRUint32 hash = 0;
|
|
PRUint32 off = 0;
|
|
PRUint32 len = mKey.Length();
|
|
|
|
if (len < 16) {
|
|
for (PRUint32 i = len ; i > 0; i--) {
|
|
hash = (hash * 37) + val[off++];
|
|
}
|
|
} else { // only sample some characters
|
|
PRUint32 skip = len / 8;
|
|
for (PRUint32 i = len ; i > 0; i -= skip, off += skip) {
|
|
hash = (hash * 39) + val[off];
|
|
}
|
|
}
|
|
NS_FREE_STR_BUF(val)
|
|
((nsStringHashKey*)this)->mHashValue = hash;//^= (hash & 0x7FFFFFFF);
|
|
((nsStringHashKey*)this)->mHashValid = 1;
|
|
}
|
|
return mHashValue;
|
|
}
|
|
|
|
|
|
|
|
nsHashtable * nsRadioGroup::mRadioGroupHashtable = new nsHashtable(8);
|
|
|
|
PRBool HashtableEnum(nsHashKey *aKey, void *aData) {
|
|
printf("HashtableEnum %s\n", aKey);
|
|
return PR_TRUE;
|
|
}
|
|
|
|
|
|
|
|
NS_IMPL_ADDREF(nsRadioGroup)
|
|
NS_IMPL_RELEASE(nsRadioGroup)
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// nsRadioGroup constructor
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
nsRadioGroup::nsRadioGroup() : nsObject()
|
|
{
|
|
NS_INIT_REFCNT();
|
|
mChildren = NULL;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// nsRadioGroup destructor
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
nsRadioGroup::~nsRadioGroup()
|
|
{
|
|
if (mChildren) {
|
|
mChildren = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// nsRadioGroup static methods
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
nsRadioGroup * nsRadioGroup::getNamedRadioGroup(const nsString & aName) {
|
|
nsStringHashKey key(aName);
|
|
nsRadioGroup * group = (nsRadioGroup *)mRadioGroupHashtable->Get((nsHashKey *)&key);
|
|
return group;
|
|
}
|
|
|
|
NS_EXPORT nsIRadioGroup * NS_GetRadioGroup(const nsString &aName) {
|
|
return nsRadioGroup::getNamedRadioGroup(aName);
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// Query interface implementation
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
nsresult nsRadioGroup::QueryInterface(const nsIID& aIID, void** aInstancePtr)
|
|
{
|
|
nsresult result = nsObject::QueryInterface(aIID, aInstancePtr);
|
|
|
|
static NS_DEFINE_IID(kInsRadioGroupIID, NS_IRADIOGROUP_IID);
|
|
if (result == NS_NOINTERFACE && aIID.Equals(kInsRadioGroupIID)) {
|
|
*aInstancePtr = (void*) ((nsIRadioGroup*)this);
|
|
NS_ADDREF_THIS();
|
|
result = NS_OK;
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// Gives a name to this group of radio buttons
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
NS_METHOD nsRadioGroup::SetName(const nsString &aName)
|
|
{
|
|
mName.SetLength(0);
|
|
mName.Append(aName);
|
|
mRadioGroupHashtable->Put(new nsStringHashKey(aName), this);
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// Adds a nsRadioButton to this group
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
NS_METHOD nsRadioGroup::Clicked(nsIRadioButton * aChild)
|
|
{
|
|
#if 0
|
|
if (mChildren) {
|
|
nsIEnumerator * enumerator = GetChildren();
|
|
nsIRadioButton * child = (nsIRadioButton*)enumerator->Next();
|
|
while (child) {
|
|
child->SetStateNoNotify((PRBool)(child == aChild));
|
|
NS_RELEASE(child);
|
|
child = (nsIRadioButton*)enumerator->Next();
|
|
}
|
|
NS_RELEASE(enumerator);
|
|
}
|
|
#endif
|
|
return NS_OK;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// Adds a nsRadioButton to this group
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
NS_METHOD nsRadioGroup::Add(nsIRadioButton * aChild)
|
|
{
|
|
if (!mChildren) {
|
|
mChildren = new Enumerator();
|
|
}
|
|
|
|
mChildren->Append(aChild);
|
|
return NS_OK;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// Removes a nsRadioButton from this group
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
NS_METHOD nsRadioGroup::Remove(nsIRadioButton * aChild)
|
|
{
|
|
if (mChildren) {
|
|
mChildren->Remove(aChild);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// Get this window's list of children
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
nsIEnumerator* nsRadioGroup::GetChildren()
|
|
{
|
|
if (mChildren) {
|
|
mChildren->Reset();
|
|
NS_ADDREF(mChildren);
|
|
return mChildren;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// Constructor
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
#define INITIAL_SIZE 2
|
|
|
|
nsRadioGroup::Enumerator::Enumerator()
|
|
{
|
|
mRefCnt = 0;
|
|
mArraySize = INITIAL_SIZE;
|
|
mChildrens = (nsIRadioButton**)new DWORD[mArraySize];
|
|
memset(mChildrens, 0, sizeof(DWORD) * mArraySize);
|
|
mCurrentPosition = 0;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// Destructor
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
nsRadioGroup::Enumerator::~Enumerator()
|
|
{
|
|
if (mChildrens) {
|
|
for (int i = 0; mChildrens[i] && i < mArraySize; i++) {
|
|
NS_RELEASE(mChildrens[i]);
|
|
}
|
|
|
|
delete[] mChildrens;
|
|
}
|
|
}
|
|
|
|
//
|
|
// nsISupports methods
|
|
//
|
|
NS_IMPL_ISUPPORTS(nsRadioGroup::Enumerator, NS_IENUMERATOR_IID);
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// Get enumeration next element. Return null at the end
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
nsISupports* nsRadioGroup::Enumerator::Next()
|
|
{
|
|
if (mCurrentPosition < mArraySize && mChildrens[mCurrentPosition]) {
|
|
NS_ADDREF(mChildrens[mCurrentPosition]);
|
|
return mChildrens[mCurrentPosition++];
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// Reset enumerator internal pointer to the beginning
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
void nsRadioGroup::Enumerator::Reset()
|
|
{
|
|
mCurrentPosition = 0;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// Append an element
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
void nsRadioGroup::Enumerator::Append(nsIRadioButton* aRadioButton)
|
|
{
|
|
NS_PRECONDITION(aRadioButton, "Adding a null radio button to a radio group");
|
|
if (aRadioButton) {
|
|
int pos;
|
|
for (pos = 0; pos < mArraySize && mChildrens[pos]; pos++);
|
|
if (pos == mArraySize) {
|
|
GrowArray();
|
|
}
|
|
mChildrens[pos] = aRadioButton;
|
|
NS_ADDREF(aRadioButton);
|
|
}
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// Remove an element
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
void nsRadioGroup::Enumerator::Remove(nsIRadioButton* aRadioButton)
|
|
{
|
|
int pos;
|
|
for(pos = 0; mChildrens[pos] && (mChildrens[pos] != aRadioButton); pos++);
|
|
if (mChildrens[pos] == aRadioButton) {
|
|
NS_RELEASE(aRadioButton);
|
|
memcpy(mChildrens + pos, mChildrens + pos + 1, mArraySize - pos - 1);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// Grow the size of the children array
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
void nsRadioGroup::Enumerator::GrowArray()
|
|
{
|
|
mArraySize <<= 1;
|
|
nsIRadioButton **newArray = (nsIRadioButton**)new DWORD[mArraySize];
|
|
memset(newArray, 0, sizeof(DWORD) * mArraySize);
|
|
memcpy(newArray, mChildrens, (mArraySize>>1) * sizeof(DWORD));
|
|
mChildrens = newArray;
|
|
}
|
|
|
|
|