#endif
int iRow = pNmItemAct->iItem;
int iCol = pNmItemAct->iSubItem;
+ if (iRow < 0)
+ return false;
- if (iRow >= 0)
+ int update = 0;
+
+ if (headers[iCol].type == ListView::ControlType::popup)
+ {
+ POINT p;
+ // position pop-up menu at the location of the click
+ GetCursorPos(&p);
+
+ update = popup_menu(iRow, iCol, p);
+ }
+ else
{
// Inform the item of the click
- int update = (*contents)[iRow]->do_action(iCol);
+ update = (*contents)[iRow]->do_action(iCol, 0);
+ }
- // Update items, if needed
- if (update > 0)
- {
- ListView_RedrawItems(hWndListView, iRow, iRow + update -1);
- }
+ // Update items, if needed
+ if (update > 0)
+ {
+ ListView_RedrawItems(hWndListView, iRow, iRow + update -1);
}
+
return true;
}
break;
result = CDRF_SKIPDEFAULT;
}
break;
+
+ case ListView::ControlType::popup:
+ {
+ // let the control draw the text, but notify us afterwards
+ result = CDRF_NOTIFYPOSTPAINT;
+ }
+ break;
+ }
+
+ *pResult = result;
+ return true;
+ }
+ case CDDS_SUBITEM | CDDS_ITEMPOSTPAINT:
+ {
+ LRESULT result = CDRF_DODEFAULT;
+ int iCol = pNmLvCustomDraw->iSubItem;
+ int iRow = pNmLvCustomDraw->nmcd.dwItemSpec;
+
+ switch (headers[iCol].type)
+ {
+ default:
+ result = CDRF_DODEFAULT;
+ break;
+
+ case ListView::ControlType::popup:
+ {
+ // draw the control at the RHS of the cell
+ RECT r;
+ ListView_GetSubItemRect(hWndListView, iRow, iCol, LVIR_BOUNDS, &r);
+ r.left = r.right - GetSystemMetrics(SM_CXVSCROLL);
+ DrawFrameControl(pNmLvCustomDraw->nmcd.hdc, &r, DFC_SCROLL,DFCS_SCROLLCOMBOBOX);
+
+ result = CDRF_DODEFAULT;
+ }
+ break;
}
*pResult = result;
return true;
{
empty_list_text = text;
}
+
+int
+ListView::popup_menu(int iRow, int iCol, POINT p)
+{
+ int update = 0;
+ // construct menu
+ HMENU hMenu = CreatePopupMenu();
+
+ MENUITEMINFO mii;
+ memset(&mii, 0, sizeof(mii));
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_FTYPE | MIIM_STATE | MIIM_STRING | MIIM_ID;
+ mii.fType = MFT_STRING;
+
+ ActionList *al = (*contents)[iRow]->get_actions(iCol);
+
+ Actions::iterator i;
+ int j = 1;
+ for (i = al->list.begin (); i != al->list.end (); ++i, ++j)
+ {
+ BOOL res;
+ mii.dwTypeData = (char *)i->name.c_str();
+ mii.fState = (i->selected ? MFS_CHECKED : MFS_UNCHECKED |
+ i->enabled ? MFS_ENABLED : MFS_DISABLED);
+ mii.wID = j;
+
+ res = InsertMenuItem(hMenu, -1, TRUE, &mii);
+ if (!res) Log (LOG_BABBLE) << "InsertMenuItem failed " << endLog;
+ }
+
+ int id = TrackPopupMenu(hMenu,
+ TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_NOANIMATION,
+ p.x, p.y, 0, hWndListView, NULL);
+
+ // Inform the item of the menu choice
+ if (id)
+ update = (*contents)[iRow]->do_action(iCol, al->list[id-1].id);
+
+ DestroyMenu(hMenu);
+ delete al;
+
+ return update;
+}
#ifndef SETUP_LISTVIEW_H
#define SETUP_LISTVIEW_H
+#include "ActionList.h"
#include "win32.h"
#include <vector>
public:
virtual ~ListViewLine() {};
virtual const std::string get_text(int col) const = 0;
- virtual int do_action(int col) = 0;
+ virtual ActionList *get_actions(int col) const = 0;
+ virtual int do_action(int col, int id) = 0;
};
typedef std::vector<ListViewLine *> ListViewContents;
{
text,
checkbox,
+ popup,
};
class Header
void initColumns(HeaderList hl);
void empty(void);
+ int popup_menu(int iRow, int iCol, POINT p);
};
#endif /* SETUP_LISTVIEW_H */
#include "package_db.h"
#include "PickView.h"
#include "window.h"
+#include "package_meta.h"
const std::string
PickCategoryLine::get_text (int col_num) const
}
int
-PickCategoryLine::do_action(int col_num)
+PickCategoryLine::do_action(int col_num, int action_id)
{
if (col_num == pkgname_col)
{
else if (col_num == new_col)
{
theView.GetParent ()->SetBusy ();
- int u = cat_tree->do_action((packagemeta::_actions)((cat_tree->action() + 1) % 4), theView.deftrust);
+ int u = cat_tree->do_action((packagemeta::_actions)(action_id), theView.deftrust);
theView.GetParent ()->ClearBusy ();
return u;
}
return 1;
}
+
+ActionList *
+PickCategoryLine::get_actions(int col) const
+{
+ ActionList *al = new ActionList();
+ packagemeta::_actions current_default = cat_tree->action();
+
+ al->add("Default", (int)packagemeta::Default_action, (current_default == packagemeta::Default_action), TRUE);
+ al->add("Install", (int)packagemeta::Install_action, (current_default == packagemeta::Install_action), TRUE);
+ al->add(packagedb::task == PackageDB_Install ? "Reinstall" : "Retrieve",
+ (int)packagemeta::Reinstall_action, (current_default == packagemeta::Reinstall_action), TRUE);
+ al->add("Uninstall", (int)packagemeta::Uninstall_action, (current_default == packagemeta::Uninstall_action), TRUE);
+
+ return al;
+}
}
const std::string get_text(int col) const;
- int do_action(int col);
+ ActionList *get_actions(int col) const;
+ int do_action(int col, int action_id);
private:
CategoryTree * cat_tree;
}
int
-PickPackageLine::do_action(int col_num)
+PickPackageLine::do_action(int col_num, int action_id)
{
if (col_num == new_col)
{
- pkg.set_action (theView.deftrust);
+ pkg.select_action(action_id, theView.deftrust);
return 1;
}
-
if (col_num == bintick_col)
{
if (pkg.desired.accessible ())
return 0;
}
+
+ActionList *
+PickPackageLine::get_actions(int col_num) const
+{
+ if (col_num == new_col)
+ {
+ return pkg.list_actions (theView.deftrust);
+ }
+
+ return NULL;
+}
{
};
const std::string get_text(int col) const;
- int do_action(int col);
+ ActionList *get_actions(int col_num) const;
+ int do_action(int col, int action_id);
private:
packagemeta & pkg;
PickView & theView;
static ListView::Header pkg_headers[] = {
{"Package", LVCFMT_LEFT, ListView::ControlType::text},
{"Current", LVCFMT_LEFT, ListView::ControlType::text},
- {"New", LVCFMT_LEFT, ListView::ControlType::text},
+ {"New", LVCFMT_LEFT, ListView::ControlType::popup},
{"Bin?", LVCFMT_LEFT, ListView::ControlType::checkbox},
{"Src?", LVCFMT_LEFT, ListView::ControlType::checkbox},
{"Categories", LVCFMT_LEFT, ListView::ControlType::text},
return desired.Canonical_version ();
}
-/* Set the next action given a current action. */
-void
-packagemeta::set_action (trusts const trust)
-{
- std::set<packageversion>::iterator i;
-
- /* Keep the picked settings of the former desired version, if any, and make
- sure at least one of them is picked. If both are unpicked, pick the
- binary version. */
- bool source_picked = desired && srcpicked ();
- bool binary_picked = !desired || picked () || !source_picked;
-
- /* If we're on "Keep" on the installed version, and the version is available,
- switch to "Reinstall". */
- if (desired && desired == installed && !picked ()
- && desired.accessible ())
- {
- pick (true);
- return;
- }
-
- if (!desired)
- {
- /* From "Uninstall" switch to the first version. From "Skip" switch to
- the first version as well, unless the user picks for the first time.
- In that case switch to the trustp version immediately. */
- if (installed || user_picked)
- i = versions.begin ();
- else
- for (i = versions.begin ();
- i != versions.end () && *i != trustp (false, trust);
- ++i)
- ;
- }
- else
- {
- /* Otherwise switch to the next version. */
- for (i = versions.begin (); i != versions.end () && *i != desired; ++i)
- ;
- ++i;
- }
- /* If there's another version in the list, switch to it, otherwise
- switch to "Uninstall". */
- if (i != versions.end ())
- {
- desired = *i;
- /* If the next version is the installed version, unpick it. This will
- have the desired effect to show the package in "Keep" mode. See also
- above for the code switching to "Reinstall". */
- pick (desired != installed && binary_picked);
- srcpick (desired.sourcePackage().accessible () && source_picked);
- }
- else
- {
- desired = packageversion ();
- pick(false);
- srcpick(false);
- }
-
- /* Memorize the fact that the user picked at least once. */
- if (!installed)
- user_picked = true;
-}
-
void
packagemeta::select_action (int id, trusts const deftrust)
{
};
static const char *action_caption (_actions value);
- void set_action (trusts const t);
void set_action (_actions, packageversion const & default_version);
ActionList *list_actions(trusts const trust);
void select_action (int id, trusts const deftrust);