Kaydet (Commit) e5755f40 authored tarafından Noel Power's avatar Noel Power

treelist for autofilter ( nested nodes for dates ) ( using SvxTreeListBox )

Attempt at trying to get more interopable behavior, imho the way dates are
presented in the autofilter of the "other" well known spreadsheet application
is very nice and intuitive. This attempt here is lacking in that

a) for some reason I am not getting the node icons ( and subsequently can't sing
le click anything to expand the nodes ) Only double clicking works to expand
b) the 'check' behaviour is not quite right, e.g. as simple example is if all
nodes of a particular date are unset then clicking the leaf node ( e.g. day )
wont set the ancestor nodes.

Change-Id: Iaa89cac21fb18074ff64a984f099a35851c2fe3c
üst 37e36eca
...@@ -27,13 +27,15 @@ public: ...@@ -27,13 +27,15 @@ public:
}; };
ScTypedStrData( const OUString& rStr, double nVal = 0.0, ScTypedStrData( const OUString& rStr, double nVal = 0.0,
StringType eType = Standard ); StringType eType = Standard, bool bDate = false );
ScTypedStrData( const ScTypedStrData& rCpy ); ScTypedStrData( const ScTypedStrData& rCpy );
bool IsStrData() const; bool IsStrData() const;
bool IsDate() const;
SC_DLLPUBLIC const OUString& GetString() const; SC_DLLPUBLIC const OUString& GetString() const;
StringType GetStringType() const; StringType GetStringType() const;
double GetValue() const { return mfValue; }
struct LessCaseSensitive : std::binary_function<ScTypedStrData, ScTypedStrData, bool> struct LessCaseSensitive : std::binary_function<ScTypedStrData, ScTypedStrData, bool>
{ {
...@@ -62,6 +64,7 @@ private: ...@@ -62,6 +64,7 @@ private:
OUString maStrValue; OUString maStrValue;
double mfValue; double mfValue;
StringType meStrType; StringType meStrType;
bool mbIsDate;
}; };
class FindTypedStrData : std::unary_function<ScTypedStrData, bool> class FindTypedStrData : std::unary_function<ScTypedStrData, bool>
......
...@@ -1795,15 +1795,17 @@ class FilterEntriesHandler ...@@ -1795,15 +1795,17 @@ class FilterEntriesHandler
} }
short nType = pFormatter->GetType(nFormat); short nType = pFormatter->GetType(nFormat);
bool bDate = false;
if ((nType & NUMBERFORMAT_DATE) && !(nType & NUMBERFORMAT_TIME)) if ((nType & NUMBERFORMAT_DATE) && !(nType & NUMBERFORMAT_TIME))
{ {
// special case for date values. Disregard the time // special case for date values. Disregard the time
// element if the number format is of date type. // element if the number format is of date type.
fVal = rtl::math::approxFloor(fVal); fVal = rtl::math::approxFloor(fVal);
mbHasDates = true; mbHasDates = true;
bDate = true;
} }
// maybe extend ScTypedStrData enum is also an option here
mrStrings.push_back(ScTypedStrData(aStr, fVal, ScTypedStrData::Value)); mrStrings.push_back(ScTypedStrData(aStr, fVal, ScTypedStrData::Value,bDate));
} }
public: public:
......
...@@ -20,6 +20,9 @@ bool ScTypedStrData::LessCaseSensitive::operator() (const ScTypedStrData& left, ...@@ -20,6 +20,9 @@ bool ScTypedStrData::LessCaseSensitive::operator() (const ScTypedStrData& left,
if (left.meStrType == Value) if (left.meStrType == Value)
return left.mfValue < right.mfValue; return left.mfValue < right.mfValue;
if (left.mbIsDate != right.mbIsDate)
return left.mbIsDate < right.mbIsDate;
return ScGlobal::GetCaseCollator()->compareString( return ScGlobal::GetCaseCollator()->compareString(
left.maStrValue, right.maStrValue) < 0; left.maStrValue, right.maStrValue) < 0;
} }
...@@ -32,6 +35,9 @@ bool ScTypedStrData::LessCaseInsensitive::operator() (const ScTypedStrData& left ...@@ -32,6 +35,9 @@ bool ScTypedStrData::LessCaseInsensitive::operator() (const ScTypedStrData& left
if (left.meStrType == Value) if (left.meStrType == Value)
return left.mfValue < right.mfValue; return left.mfValue < right.mfValue;
if (left.mbIsDate != right.mbIsDate)
return left.mbIsDate < right.mbIsDate;
return ScGlobal::GetCollator()->compareString( return ScGlobal::GetCollator()->compareString(
left.maStrValue, right.maStrValue) < 0; left.maStrValue, right.maStrValue) < 0;
} }
...@@ -44,6 +50,9 @@ bool ScTypedStrData::EqualCaseSensitive::operator() (const ScTypedStrData& left, ...@@ -44,6 +50,9 @@ bool ScTypedStrData::EqualCaseSensitive::operator() (const ScTypedStrData& left,
if (left.meStrType == Value && left.mfValue != right.mfValue) if (left.meStrType == Value && left.mfValue != right.mfValue)
return false; return false;
if (left.mbIsDate != right.mbIsDate )
return false;
return ScGlobal::GetCaseCollator()->compareString( return ScGlobal::GetCaseCollator()->compareString(
left.maStrValue, right.maStrValue) == 0; left.maStrValue, right.maStrValue) == 0;
} }
...@@ -56,6 +65,9 @@ bool ScTypedStrData::EqualCaseInsensitive::operator() (const ScTypedStrData& lef ...@@ -56,6 +65,9 @@ bool ScTypedStrData::EqualCaseInsensitive::operator() (const ScTypedStrData& lef
if (left.meStrType == Value && left.mfValue != right.mfValue) if (left.meStrType == Value && left.mfValue != right.mfValue)
return false; return false;
if (left.mbIsDate != right.mbIsDate )
return false;
return ScGlobal::GetCollator()->compareString( return ScGlobal::GetCollator()->compareString(
left.maStrValue, right.maStrValue) == 0; left.maStrValue, right.maStrValue) == 0;
} }
...@@ -75,21 +87,28 @@ bool ScTypedStrData::operator< (const ScTypedStrData& r) const ...@@ -75,21 +87,28 @@ bool ScTypedStrData::operator< (const ScTypedStrData& r) const
} }
ScTypedStrData::ScTypedStrData( ScTypedStrData::ScTypedStrData(
const OUString& rStr, double nVal, StringType nType ) : const OUString& rStr, double nVal, StringType nType, bool bDate ) :
maStrValue(rStr), maStrValue(rStr),
mfValue(nVal), mfValue(nVal),
meStrType(nType) {} meStrType(nType),
mbIsDate( bDate ) {}
ScTypedStrData::ScTypedStrData( const ScTypedStrData& rCpy ) : ScTypedStrData::ScTypedStrData( const ScTypedStrData& rCpy ) :
maStrValue(rCpy.maStrValue), maStrValue(rCpy.maStrValue),
mfValue(rCpy.mfValue), mfValue(rCpy.mfValue),
meStrType(rCpy.meStrType) {} meStrType(rCpy.meStrType),
mbIsDate( rCpy.mbIsDate ) {}
bool ScTypedStrData::IsStrData() const bool ScTypedStrData::IsStrData() const
{ {
return meStrType != Value; return meStrType != Value;
} }
bool ScTypedStrData::IsDate() const
{
return mbIsDate;
}
const OUString& ScTypedStrData::GetString() const const OUString& ScTypedStrData::GetString() const
{ {
return maStrValue; return maStrValue;
......
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
#include <com/sun/star/accessibility/XAccessible.hpp> #include <com/sun/star/accessibility/XAccessible.hpp>
#include <com/sun/star/accessibility/XAccessibleContext.hpp> #include <com/sun/star/accessibility/XAccessibleContext.hpp>
#include "svtools/fmtfield.hxx"
#include "document.hxx"
using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::Reference;
using ::com::sun::star::accessibility::XAccessible; using ::com::sun::star::accessibility::XAccessible;
...@@ -850,6 +852,11 @@ void ScMenuFloatingWindow::terminateAllPopupMenus() ...@@ -850,6 +852,11 @@ void ScMenuFloatingWindow::terminateAllPopupMenus()
mpParentMenu->terminateAllPopupMenus(); mpParentMenu->terminateAllPopupMenus();
} }
ScDocument* ScMenuFloatingWindow::getDoc()
{
return mpDoc;
}
// ============================================================================ // ============================================================================
ScCheckListMenuWindow::Config::Config() : ScCheckListMenuWindow::Config::Config() :
...@@ -1078,7 +1085,7 @@ void ScCheckListMenuWindow::setAllMemberState(bool bSet) ...@@ -1078,7 +1085,7 @@ void ScCheckListMenuWindow::setAllMemberState(bool bSet)
{ {
size_t n = maMembers.size(); size_t n = maMembers.size();
for (size_t i = 0; i < n; ++i) for (size_t i = 0; i < n; ++i)
maChecks.CheckEntryPos(static_cast<sal_uInt16>(i), bSet); maChecks.CheckEntryPos( maMembers[i].maName, maMembers[i].mpParent, bSet);
if (!maConfig.mbAllowEmptySet) if (!maConfig.mbAllowEmptySet)
// We need to have at least one member selected. // We need to have at least one member selected.
...@@ -1088,8 +1095,9 @@ void ScCheckListMenuWindow::setAllMemberState(bool bSet) ...@@ -1088,8 +1095,9 @@ void ScCheckListMenuWindow::setAllMemberState(bool bSet)
void ScCheckListMenuWindow::selectCurrentMemberOnly(bool bSet) void ScCheckListMenuWindow::selectCurrentMemberOnly(bool bSet)
{ {
setAllMemberState(!bSet); setAllMemberState(!bSet);
sal_uInt16 nSelected = maChecks.GetSelectEntryPos(); // sal_uInt16 nSelected = maChecks.GetSelectEntryPos();
maChecks.CheckEntryPos(nSelected, bSet); SvTreeListEntry* pEntry = maChecks.GetCurEntry();
maChecks.CheckEntryPos(pEntry, bSet );
} }
void ScCheckListMenuWindow::cycleFocus(bool bReverse) void ScCheckListMenuWindow::cycleFocus(bool bReverse)
...@@ -1160,7 +1168,9 @@ IMPL_LINK( ScCheckListMenuWindow, CheckHdl, SvTreeListBox*, pChecks ) ...@@ -1160,7 +1168,9 @@ IMPL_LINK( ScCheckListMenuWindow, CheckHdl, SvTreeListBox*, pChecks )
{ {
if (pChecks != &maChecks) if (pChecks != &maChecks)
return 0; return 0;
SvTreeListEntry* pEntry = pChecks->GetHdlEntry();
if ( pEntry )
maChecks.CheckEntryPos( pEntry, ( pChecks->GetCheckButtonState( pEntry ) == SV_BUTTON_CHECKED ) );
size_t nNumChecked = maChecks.GetCheckedEntryCount(); size_t nNumChecked = maChecks.GetCheckedEntryCount();
if (nNumChecked == maMembers.size()) if (nNumChecked == maMembers.size())
// all members visible // all members visible
...@@ -1267,14 +1277,177 @@ void ScCheckListMenuWindow::setMemberSize(size_t n) ...@@ -1267,14 +1277,177 @@ void ScCheckListMenuWindow::setMemberSize(size_t n)
maMembers.reserve(n); maMembers.reserve(n);
} }
void ScCheckListMenuWindow::addDateMember(const OUString& rsName, double nVal, bool bVisible)
{
ScDocument* pDoc = getDoc();
if ( pDoc )
{
SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
OUString rsDate;
if ( pFormatter )
{
OUString sFormat("YYYY/MMMM/DD");
Color* pColor = NULL;
pFormatter->GetPreviewString(sFormat,
nVal,
rsDate,
&pColor,
ScGlobal::eLnge );
}
maChecks.SetUpdateMode(false);
sal_Int32 nIndex = 0;
std::vector< OUString > vParts;
OUString sParent;
SvTreeListEntry* pParent = NULL;
int count = 0;
do
{
OUString sPart = rsDate.getToken( 0, '/', nIndex );
bool bLeaf = ( ++count == 3 );
SvTreeListEntry* pChild = maChecks.FindEntry( pParent, sPart );
if ( !pChild )
{
if ( bLeaf )
pChild = maChecks.SvTreeListBox::InsertEntry( sPart, pParent, sal_False, LISTBOX_APPEND, NULL, SvLBoxButtonKind_enabledCheckbox );
else
pChild = maChecks.SvTreeListBox::InsertEntry( sPart, pParent, sal_True, LISTBOX_APPEND, NULL, SvLBoxButtonKind_enabledCheckbox );
Member aMember;
aMember.maName = sPart;
aMember.maRealName = rsName;
aMember.mbDate = true;
aMember.mbLeaf = bLeaf;
aMember.mbVisible = bVisible;
aMember.mpParent = pParent;
maMembers.push_back(aMember);
}
sParent = sPart;
pParent = pChild;
} while ( nIndex >= 0 );
maChecks.SetUpdateMode(true);
}
}
void ScCheckListMenuWindow::addMember(const OUString& rName, bool bVisible) void ScCheckListMenuWindow::addMember(const OUString& rName, bool bVisible)
{ {
Member aMember; Member aMember;
aMember.maName = rName; aMember.maName = rName;
aMember.mbDate = false;
aMember.mbLeaf = true;
aMember.mbVisible = bVisible; aMember.mbVisible = bVisible;
aMember.mpParent = NULL;
maMembers.push_back(aMember); maMembers.push_back(aMember);
} }
SvTreeListEntry* ScCheckListBox::FindEntry( SvTreeListEntry* pParent, const OUString& sNode )
{
sal_uInt16 nRootPos = 0;
SvTreeListEntry* pEntry = pParent ? FirstChild( pParent ) : GetEntry( nRootPos );
while ( pEntry )
{
if ( sNode.equals(GetEntryText( pEntry )) )
return pEntry;
pEntry = pParent ? NextSibling( pEntry ) : GetEntry( ++nRootPos );
}
return NULL;
}
void ScCheckListBox::Init()
{
mpCheckButton = new SvLBoxButtonData( this );
EnableCheckButton( mpCheckButton );
SetNodeDefaultImages();
}
sal_Bool ScCheckListBox::IsChecked( OUString& sName, SvTreeListEntry* pParent )
{
SvTreeListEntry* pEntry = FindEntry( pParent, sName );
if ( pEntry && GetCheckButtonState( pEntry ) == SV_BUTTON_CHECKED)
return sal_True;
return sal_False;
}
void ScCheckListBox::CheckEntryPos( OUString& sName, SvTreeListEntry* pParent, sal_Bool bCheck )
{
SvTreeListEntry* pEntry = FindEntry( pParent, sName );
if ( pEntry )
CheckEntryPos( pEntry, bCheck );
}
void ScCheckListBox::CheckEntryPos( SvTreeListEntry* pParent, sal_Bool bCheck )
{
// currently pParent ( and *all* children ) are checked with state of bCheck
// *BUT* if this is not a Root node then bCheck here should also influence the
// ancestor hierarchy ( e.g. a child node checked or uncheck MAY need to check/uncheck
// the parent/grandparent node )
if ( pParent )
{
SetCheckButtonState(
pParent, bCheck ? SvButtonState( SV_BUTTON_CHECKED ) :
SvButtonState( SV_BUTTON_UNCHECKED ) );
}
SvTreeListEntry* pEntry = pParent ? FirstChild( pParent ) : First();
while ( pEntry )
{
CheckEntryPos( pEntry, bCheck );
pEntry = NextSibling( pEntry );
}
}
SvTreeListEntry* ScCheckListBox::CountCheckedEntries( SvTreeListEntry* pParent, sal_uLong& nCount ) const
{
if ( pParent && GetCheckButtonState( pParent ) == SV_BUTTON_CHECKED )
nCount++;
// Iterate over the children
SvTreeListEntry* pEntry = pParent ? FirstChild( pParent ) : First();
while ( pEntry )
{
CountCheckedEntries( pEntry, nCount );
pEntry = NextSibling( pEntry );
}
return NULL;
}
sal_uInt16 ScCheckListBox::GetCheckedEntryCount() const
{
sal_uLong nCount = 0;
CountCheckedEntries( NULL, nCount );
return nCount;
}
void ScCheckListBox::ExpandChildren( SvTreeListEntry* pParent )
{
if ( pParent )
Expand( pParent );
// Iterate over the children
SvTreeListEntry* pEntry = pParent ? FirstChild( pParent ) : First();
while ( pEntry )
{
ExpandChildren( pEntry );
pEntry = NextSibling( pEntry );
}
}
void ScCheckListBox::KeyInput( const KeyEvent& rKEvt )
{
const KeyCode& rKey = rKEvt.GetKeyCode();
if ( rKey.GetCode() == KEY_RETURN || rKey.GetCode() == KEY_SPACE )
{
SvTreeListEntry* pEntry = GetCurEntry();
if ( pEntry )
{
sal_Bool bCheck = ( GetCheckButtonState( pEntry ) == SV_BUTTON_CHECKED );
CheckEntryPos( pEntry, !bCheck );
if ( bCheck != ( GetCheckButtonState( pEntry ) == SV_BUTTON_CHECKED ) )
CheckButtonHdl();
}
}
else if ( GetEntryCount() )
SvTreeListBox::KeyInput( rKEvt );
}
void ScCheckListMenuWindow::initMembers() void ScCheckListMenuWindow::initMembers()
{ {
size_t n = maMembers.size(); size_t n = maMembers.size();
...@@ -1282,8 +1455,19 @@ void ScCheckListMenuWindow::initMembers() ...@@ -1282,8 +1455,19 @@ void ScCheckListMenuWindow::initMembers()
maChecks.SetUpdateMode(false); maChecks.SetUpdateMode(false);
for (size_t i = 0; i < n; ++i) for (size_t i = 0; i < n; ++i)
{ {
maChecks.InsertEntry(maMembers[i].maName); if ( !maMembers[ i ].mbDate )
maChecks.CheckEntryPos(static_cast< sal_uInt16 >( i ), maMembers[i].mbVisible); {
maChecks.InsertEntry(maMembers[i].maName, NULL, sal_False, LISTBOX_APPEND, NULL,
SvLBoxButtonKind_enabledCheckbox );
}
// Expand all nodes of dates
// Needs better behaviour, what gets expanded how much etc. ( depending
// on the tree contents )
else if ( maMembers[ i ].mpParent == NULL )
{
maChecks.ExpandChildren( maChecks.FindEntry( NULL, maMembers[ i ].maName ) );
}
maChecks.CheckEntryPos( maMembers[i].maName, maMembers[i].mpParent, maMembers[i].mbVisible);
if (maMembers[i].mbVisible) if (maMembers[i].mbVisible)
++nVisMemCount; ++nVisMemCount;
} }
...@@ -1323,8 +1507,16 @@ void ScCheckListMenuWindow::getResult(ResultType& rResult) ...@@ -1323,8 +1507,16 @@ void ScCheckListMenuWindow::getResult(ResultType& rResult)
size_t n = maMembers.size(); size_t n = maMembers.size();
for (size_t i = 0; i < n; ++i) for (size_t i = 0; i < n; ++i)
{ {
bool bState = maChecks.IsChecked(static_cast< sal_uInt16 >( i )); if ( maMembers[i].mbLeaf )
aResult.insert(ResultType::value_type(maMembers[i].maName, bState)); {
bool bState = maChecks.IsChecked( maMembers[i].maName, maMembers[i].mpParent );
OUString sName;
if ( maMembers[i].mbDate )
sName = maMembers[i].maRealName;
else
sName = maMembers[i].maName;
aResult.insert(ResultType::value_type(sName, bState));
}
} }
rResult.swap(aResult); rResult.swap(aResult);
} }
......
...@@ -186,6 +186,24 @@ private: ...@@ -186,6 +186,24 @@ private:
ScMenuFloatingWindow* mpParentMenu; ScMenuFloatingWindow* mpParentMenu;
}; };
class ScCheckListBox : public SvTreeListBox
{
SvLBoxButtonData* mpCheckButton;
SvTreeListEntry* CountCheckedEntries( SvTreeListEntry* pParent, sal_uLong& nCount ) const;
public:
ScCheckListBox( Window* pParent, WinBits nWinStyle = 0 ) : SvTreeListBox( pParent, nWinStyle ) { Init(); }
ScCheckListBox( Window* pParent, const ResId& rResId ) : SvTreeListBox( pParent, rResId ) { Init(); }
~ScCheckListBox() { delete mpCheckButton; }
void Init();
void CheckEntryPos ( OUString& sName, SvTreeListEntry* pParent, sal_Bool bCheck = sal_True );
void CheckEntryPos ( SvTreeListEntry* pEntry, sal_Bool bCheck = sal_True );
sal_Bool IsChecked( OUString& sName, SvTreeListEntry* pParent );
SvTreeListEntry* FindEntry( SvTreeListEntry* pParent, const OUString& sNode );
sal_uInt16 GetCheckedEntryCount() const;
void ExpandChildren( SvTreeListEntry* pParent );
virtual void KeyInput( const KeyEvent& rKEvt );
};
/** /**
* This class implements a popup window for field button, for quick access * This class implements a popup window for field button, for quick access
* of hide-item list, and possibly more stuff related to field options. * of hide-item list, and possibly more stuff related to field options.
...@@ -225,6 +243,7 @@ public: ...@@ -225,6 +243,7 @@ public:
virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > CreateAccessible(); virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > CreateAccessible();
void setMemberSize(size_t n); void setMemberSize(size_t n);
void addDateMember(const OUString& rName, double nVal, bool bVisible);
void addMember(const OUString& rName, bool bVisible); void addMember(const OUString& rName, bool bVisible);
void initMembers(); void initMembers();
void setConfig(const Config& rConfig); void setConfig(const Config& rConfig);
...@@ -255,10 +274,14 @@ protected: ...@@ -255,10 +274,14 @@ protected:
private: private:
struct Member struct Member
{ {
OUString maName; OUString maName; // node name
OUString maRealName;
bool mbVisible; bool mbVisible;
bool mbDate;
bool mbLeaf;
Member(); Member();
SvTreeListEntry* mpParent;
}; };
class CancelButton : public ::CancelButton class CancelButton : public ::CancelButton
...@@ -299,7 +322,9 @@ private: ...@@ -299,7 +322,9 @@ private:
DECL_LINK( CheckHdl, SvTreeListBox* ); DECL_LINK( CheckHdl, SvTreeListBox* );
private: private:
SvxCheckListBox maChecks; SvTreeListEntry* findEntry( SvTreeListEntry* pParent, const OUString& rText );
ScCheckListBox maChecks;
TriStateBox maChkToggleAll; TriStateBox maChkToggleAll;
ImageButton maBtnSelectSingle; ImageButton maBtnSelectSingle;
......
...@@ -706,7 +706,10 @@ void ScGridWindow::LaunchAutoFilterMenu(SCCOL nCol, SCROW nRow) ...@@ -706,7 +706,10 @@ void ScGridWindow::LaunchAutoFilterMenu(SCCOL nCol, SCROW nRow)
bool bSelected = true; bool bSelected = true;
if (!aSelected.empty()) if (!aSelected.empty())
bSelected = aSelected.count(aVal) > 0; bSelected = aSelected.count(aVal) > 0;
mpAutoFilterPopup->addMember(aVal, bSelected); if ( it->IsDate() )
mpAutoFilterPopup->addDateMember( aVal, it->GetValue(), bSelected );
else
mpAutoFilterPopup->addMember(aVal, bSelected);
} }
mpAutoFilterPopup->initMembers(); mpAutoFilterPopup->initMembers();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment