Skip to content

Commit

Permalink
Improvements to utils.filterpicker to allow filter function
Browse files Browse the repository at this point in the history
  • Loading branch information
nickgammon committed Sep 24, 2010
1 parent 4bede38 commit 34e9dbb
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 7 deletions.
64 changes: 57 additions & 7 deletions dialogs/FunctionListDlg.cpp
Expand Up @@ -11,6 +11,8 @@
static char THIS_FILE[] = __FILE__;
#endif

#pragma warning (disable : 4800) // forcing value to bool 'true' or 'false' (performance warning)

/////////////////////////////////////////////////////////////////////////////
// CFunctionListDlg dialog

Expand All @@ -22,6 +24,8 @@ CFunctionListDlg::CFunctionListDlg(CWnd* pParent /*=NULL*/)
m_strFilter = _T("");
//}}AFX_DATA_INIT
m_bFunctions = false;
m_bNoSort = false;
m_L = NULL;
}


Expand Down Expand Up @@ -62,7 +66,6 @@ BOOL CFunctionListDlg::ReloadList ()

m_ctlFunctions.DeleteAllItems ();

m_strFilter.MakeLower ();
m_strFilter.TrimLeft ();
m_strFilter.TrimRight ();

Expand All @@ -77,15 +80,54 @@ BOOL CFunctionListDlg::ReloadList ()
it != m_data.end ();
it++, nKeynum++)
{
string sValue = it->sValue_;
CKeyValuePair kv = *it;
string sValue = kv.sValue_;
bool bWanted = false;

if (m_L && lua_type (m_L, 1) == LUA_TFUNCTION)
{

if (sFilter.empty () || search (sValue.begin (), sValue.end (),
// Lua filter: function f (filter, key, value) ... end

// filter function (make copy)
lua_pushvalue (m_L, 1);
// what they have currently typed
lua_pushlstring (m_L, sFilter.c_str (), sFilter.size ());

// push number or string which is the key
if (kv.bNumber_)
lua_pushnumber (m_L, kv.iKey_);
else
lua_pushlstring (m_L, kv.sKey_.c_str (), kv.sKey_.size ());

// push value
lua_pushlstring (m_L, kv.sValue_.c_str (), kv.sValue_.size ());

// call the function: arg1: filter field, arg2: key, arg3: value
if (lua_pcall (m_L, 3, 1, 0)) // call with 3 args and 1 result
{
LuaError (m_L); // note that this clears the stack, so we won't call it again
lua_settop (m_L, 0); // clear stack, just in case LuaError changes behaviour
bWanted = false;
} // end of error
else
{
bWanted = lua_toboolean (m_L, -1);
lua_pop (m_L, 1); // pop result
} // end of no error

} // end of Lua filter function available
else
// no Lua function, just do a substring compare
bWanted = sFilter.empty () || search (sValue.begin (), sValue.end (),
sFilter.begin (), sFilter.end (),
nocase_compare) != sValue.end ())
nocase_compare) != sValue.end ();

if (bWanted)
{
int iPos = m_ctlFunctions.InsertItem (nItem, sValue.c_str ());
if (iPos != -1)
m_ctlFunctions.SetItemData (iPos, nKeynum);
m_ctlFunctions.SetItemData (iPos, nKeynum); // sorting changes the position

// select the exact match, if any (so, if they highlight world.Note then it is selected)

Expand All @@ -95,8 +137,8 @@ BOOL CFunctionListDlg::ReloadList ()
LVIS_FOCUSED | LVIS_SELECTED);
nItem++;

}
}
} // end of wanted in list
} // end of for loop


// if the filtering results in a single item, select it
Expand All @@ -108,6 +150,7 @@ BOOL CFunctionListDlg::ReloadList ()
return FALSE;
}

// if no filter value, put focus there so they can type one in
if (m_strFilter.IsEmpty ())
{
m_ctlFilter.SetFocus ();
Expand All @@ -132,6 +175,12 @@ BOOL CFunctionListDlg::OnInitDialog()
{
GetDlgItem(IDC_LUA_FUNCTIONS)->ShowWindow (SW_HIDE);
GetDlgItem(IDC_COPY_NAME)->ShowWindow (SW_HIDE);
}

if (m_bNoSort)
{
m_ctlFunctions.ModifyStyle (LVS_SORTASCENDING, 0);
m_ctlFunctions.ModifyStyle (LVS_SORTDESCENDING, 0);
}

return ReloadList (); // return TRUE unless you set the focus to a control
Expand Down Expand Up @@ -201,3 +250,4 @@ void CFunctionListDlg::OnUpdateNeedSelection(CCmdUI* pCmdUI)
pCmdUI->Enable(iWhich != -1);
} // end of CFunctionListDlg::OnUpdateNeedSelection


4 changes: 4 additions & 0 deletions dialogs/FunctionListDlg.h
Expand Up @@ -26,6 +26,7 @@ class CFunctionListDlg : public CDialog


bool m_bFunctions;
bool m_bNoSort;

// dialog title
CString m_strTitle;
Expand All @@ -36,6 +37,9 @@ class CFunctionListDlg : public CDialog
// chosen item
CKeyValuePair m_result;

// Lua state for filter function
lua_State * m_L;

// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CFunctionListDlg)
Expand Down
17 changes: 17 additions & 0 deletions scripting/lua_utils.cpp
Expand Up @@ -1567,11 +1567,14 @@ static int shell_execute (lua_State *L)
// arg1 is dialog title
// arg2 is table of key/value pairs - value is shown
// arg3 is initial filter
// arg4 is "no sort" boolean
// arg5 is filter function

int filterpicker (lua_State *L)
{
const char * filtertitle = luaL_optstring (L, 2, "Filter");
const char * initialfilter = luaL_optstring (L, 3, "");
const bool bNoSort = optboolean (L, 4, 0);

if (strlen (filtertitle) > 100)
luaL_error (L, "title too long (max 100 characters)");
Expand All @@ -1585,6 +1588,7 @@ CFunctionListDlg dlg;

dlg.m_strTitle = filtertitle;
dlg.m_strFilter = initialfilter;
dlg.m_bNoSort = bNoSort;

// standard Lua table iteration
for (lua_pushnil (L); lua_next (L, table) != 0; lua_pop (L, 1))
Expand Down Expand Up @@ -1618,6 +1622,19 @@ CFunctionListDlg dlg;
} // end of looping through table


if (lua_gettop (L) > 4)
{
if (!lua_isnil (L, 5))
{
luaL_checktype (L, 5, LUA_TFUNCTION);
lua_remove (L, 1); // get rid of bottom 4 items
lua_remove (L, 1);
lua_remove (L, 1);
lua_remove (L, 1);
dlg.m_L = L; // function is now at stack item 1
}
}

if (dlg.DoModal () != IDOK)
lua_pushnil (L);
else
Expand Down

0 comments on commit 34e9dbb

Please sign in to comment.