2 * Copyright (c) 2002 Robert Collins.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * A copy of the GNU General Public License can be found at
12 * Written by Robert Collins <robertc@hotmail.com>
18 #include "PickPackageLine.h"
19 #include "PickCategoryLine.h"
20 #include "package_db.h"
21 #include "package_version.h"
27 #include "LogSingleton.h"
31 static PickView::Header pkg_headers
[] = {
32 {"Current", 0, 0, true},
34 {"Bin?", 0, 0, false},
35 {"Src?", 0, 0, false},
36 {"Categories", 0, 0, true},
37 {"Package", 0, 0, true},
41 static PickView::Header cat_headers
[] = {
42 {"Category", 0, 0, true},
43 {"Current", 0, 0, true},
45 {"Bin?", 0, 0, false},
46 {"Src?", 0, 0, false},
47 {"Package", 0, 0, true},
52 const PickView::views
PickView::views::Unknown (0);
53 const PickView::views
PickView::views::PackageFull (1);
54 const PickView::views
PickView::views::Package (2);
55 const PickView::views
PickView::views::PackageKeeps (3);
56 const PickView::views
PickView::views::PackageSkips
= PickView::views (4);
57 const PickView::views
PickView::views::Category (5);
59 ATOM
PickView::WindowClassAtom
= 0;
61 // DoInsertItem - inserts an item into a header control.
62 // Returns the index of the new item.
63 // hwndHeader - handle to the header control.
64 // iInsertAfter - index of the previous item.
65 // nWidth - width of the new item.
66 // lpsz - address of the item string.
68 DoInsertItem (HWND hwndHeader
, int iInsertAfter
, int nWidth
, LPSTR lpsz
)
73 hdi
.mask
= HDI_TEXT
| HDI_FORMAT
| HDI_WIDTH
;
76 hdi
.cchTextMax
= lstrlen (hdi
.pszText
);
77 hdi
.fmt
= HDF_LEFT
| HDF_STRING
;
79 index
= SendMessage (hwndHeader
, HDM_INSERTITEM
,
80 (WPARAM
) iInsertAfter
, (LPARAM
) & hdi
);
86 PickView::set_headers ()
88 if (view_mode
== views::Unknown
)
90 if (view_mode
== views::PackageFull
||
91 view_mode
== views::Package
||
92 view_mode
== views::PackageKeeps
||
93 view_mode
== views::PackageSkips
)
95 headers
= pkg_headers
;
98 bintick_col
= new_col
+ 1;
99 srctick_col
= bintick_col
+ 1;
100 cat_col
= srctick_col
+ 1;
101 pkg_col
= cat_col
+ 1;
104 else if (view_mode
== views::Category
)
106 headers
= cat_headers
;
108 new_col
= current_col
+ 1;
109 bintick_col
= new_col
+ 1;
110 srctick_col
= bintick_col
+ 1;
112 pkg_col
= srctick_col
+ 1;
117 while (int n
= SendMessage (listheader
, HDM_GETITEMCOUNT
, 0, 0))
119 SendMessage (listheader
, HDM_DELETEITEM
, n
- 1, 0);
122 for (i
= 0; i
<= last_col
; i
++)
123 DoInsertItem (listheader
, i
, headers
[i
].width
, (char *) headers
[i
].text
);
127 PickView::note_width (PickView::Header
*hdrs
, HDC dc
, String
const &string
,
128 int addend
, int column
)
133 GetTextExtentPoint32 (dc
, string
.c_str(), string
.size(), &s
);
134 if (hdrs
[column
].width
< s
.cx
+ addend
)
135 hdrs
[column
].width
= s
.cx
+ addend
;
139 PickView::cycleViewMode ()
141 setViewMode (++view_mode
);
145 PickView::setViewMode (views mode
)
152 if (view_mode
== PickView::views::Category
)
154 contents
.ShowLabel (true);
155 /* start collapsed. TODO: make this a chooser flag */
156 for (packagedb::categoriesType::iterator n
=
157 packagedb::categories
.begin(); n
!= packagedb::categories
.end();
159 insert_category (&*n
, CATEGORY_COLLAPSED
);
163 contents
.ShowLabel (false);
164 // iterate through every package
165 for (vector
<packagemeta
*>::iterator i
= db
.packages
.begin ();
166 i
!= db
.packages
.end (); ++i
)
168 packagemeta
& pkg
= **i
;
170 if ( // "Full" : everything
171 (view_mode
== PickView::views::PackageFull
)
173 // "Partial" : packages that are being added/removed/upgraded
174 || (view_mode
== PickView::views::Package
&&
175 ((!pkg
.desired
&& pkg
.installed
) || // uninstall
177 (pkg
.desired
.picked () || // install bin
178 pkg
.desired
.sourcePackage ().picked ())))) // src
180 // "Up to date" : installed packages that will not be changed
181 || (view_mode
== PickView::views::PackageKeeps
&&
182 (pkg
.installed
&& pkg
.desired
&& !pkg
.desired
.picked ()
183 && !pkg
.desired
.sourcePackage ().picked ()))
186 || (view_mode
== PickView::views::PackageSkips
&&
187 (!pkg
.desired
&& !pkg
.installed
)))
193 RECT r
= GetClientRect ();
195 memset (&si
, 0, sizeof (si
));
196 si
.cbSize
= sizeof (si
);
197 si
.fMask
= SIF_ALL
| SIF_DISABLENOSCROLL
;
199 si
.nMax
= headers
[last_col
].x
+ headers
[last_col
].width
; // + HMARGIN;
201 SetScrollInfo (GetHWND(), SB_HORZ
, &si
, TRUE
);
203 si
.nMax
= contents
.itemcount () * row_height
;
204 si
.nPage
= r
.bottom
- header_height
;
205 SetScrollInfo (GetHWND(), SB_VERT
, &si
, TRUE
);
207 scroll_ulc_x
= scroll_ulc_y
= 0;
209 InvalidateRect (GetHWND(), &r
, TRUE
);
213 PickView::mode_caption ()
215 return view_mode
.caption ();
219 PickView::views::caption ()
230 return "Not Installed";
238 /* meant to be called on packagemeta::categories */
240 isObsolete (set
<String
, String::caseless
> &categories
)
242 set
<String
, String::caseless
>::const_iterator i
;
244 for (i
= categories
.begin (); i
!= categories
.end (); ++i
)
251 isObsolete (const String
&catname
)
253 if (catname
.casecompare ("ZZZRemovedPackages") == 0
254 || catname
.casecompare ("_", 1) == 0)
259 /* Sets the mode for showing/hiding obsolete junk packages. */
261 PickView::setObsolete (bool doit
)
269 PickView::insert_pkg (packagemeta
& pkg
)
271 if (!showObsolete
&& isObsolete (pkg
.categories
))
274 if (view_mode
!= views::Category
)
276 PickLine
& line
= *new PickPackageLine (*this, pkg
);
277 contents
.insert (line
);
281 for (set
<String
, String::caseless
>::const_iterator x
282 = pkg
.categories
.begin (); x
!= pkg
.categories
.end (); ++x
)
284 // Special case - yuck
285 if (x
->casecompare ("All") == 0)
289 PickCategoryLine
& catline
=
290 *new PickCategoryLine (*this, *db
.categories
.find (*x
), 1);
291 PickLine
& line
= *new PickPackageLine(*this, pkg
);
292 catline
.insert (line
);
293 contents
.insert (catline
);
299 PickView::insert_category (Category
*cat
, bool collapsed
)
302 if (cat
->first
.casecompare ("All") == 0 ||
303 (!showObsolete
&& isObsolete (cat
->first
)))
305 PickCategoryLine
& catline
= *new PickCategoryLine (*this, *cat
, 1, collapsed
);
306 for (vector
<packagemeta
*>::iterator i
= cat
->second
.begin ();
307 i
!= cat
->second
.end () ; ++i
)
309 PickLine
& line
= *new PickPackageLine (*this, **i
);
310 catline
.insert (line
);
312 contents
.insert (catline
);
316 PickView::views::operator++ ()
319 if (_value
> Category
._value
)
325 PickView::click (int row
, int x
)
327 return contents
.click (0, row
, x
);
332 PickView::scroll (HWND hwnd
, int which
, int *var
, int code
, int howmany
= 1)
335 si
.cbSize
= sizeof (si
);
336 si
.fMask
= SIF_ALL
| SIF_DISABLENOSCROLL
;
337 GetScrollInfo (hwnd
, which
, &si
);
342 si
.nPos
= si
.nTrackPos
;
344 case SB_THUMBPOSITION
:
353 si
.nPos
+= (row_height
* howmany
);
356 si
.nPos
-= (row_height
* howmany
);
359 si
.nPos
+= si
.nPage
* 9 / 10;
362 si
.nPos
-= si
.nPage
* 9 / 10;
366 if ((int) si
.nPos
< 0)
368 if (si
.nPos
+ si
.nPage
> (unsigned int) si
.nMax
)
369 si
.nPos
= si
.nMax
- si
.nPage
;
372 SetScrollInfo (hwnd
, which
, &si
, TRUE
);
374 int ox
= scroll_ulc_x
;
375 int oy
= scroll_ulc_y
;
379 ::GetClientRect (hwnd
, &cr
);
381 sr
.top
+= header_height
;
383 ScrollWindow (hwnd
, ox
- scroll_ulc_x
, oy
- scroll_ulc_y
, &sr
, &sr
);
387 ScrollWindow (hwnd, ox - scroll_ulc_x, 0, &sr, &sr);
389 if (ox
- scroll_ulc_x
)
391 ::GetClientRect (listheader
, &cr
);
393 // UpdateWindow (htmp);
394 ::MoveWindow (listheader
, -scroll_ulc_x
, 0,
395 headers
[last_col
].x
+
396 headers
[last_col
].width
, header_height
, TRUE
);
401 /* this means to make the 'category' column wide enough to fit the first 'n'
402 categories for each package. */
403 #define NUM_CATEGORY_COL_WIDTH 2
406 PickView::init_headers (HDC dc
)
410 for (i
= 0; headers
[i
].text
; i
++)
412 headers
[i
].width
= 0;
416 // accomodate widths of the 'bin' and 'src' checkbox columns
417 note_width (headers
, dc
, 0, HMARGIN
+ 11, bintick_col
);
418 note_width (headers
, dc
, 0, HMARGIN
+ 11, srctick_col
);
420 // accomodate the width of each category name
422 for (packagedb::categoriesType::iterator n
= packagedb::categories
.begin();
423 n
!= packagedb::categories
.end(); ++n
)
425 if (!showObsolete
&& isObsolete (n
->first
))
427 note_width (headers
, dc
, n
->first
, HMARGIN
, cat_col
);
430 /* For each package, accomodate the width of the installed version in the
431 current_col, the widths of all other versions in the new_col, and the
432 width of the sdesc for the pkg_col. Also, if this is not a Category
433 view, adjust the 'category' column so that the first NUM_CATEGORY_COL_WIDTH
434 categories from each package fits. */
435 for (vector
<packagemeta
*>::iterator n
= db
.packages
.begin ();
436 n
!= db
.packages
.end (); ++n
)
438 packagemeta
& pkg
= **n
;
439 if (!showObsolete
&& isObsolete (pkg
.categories
))
442 note_width (headers
, dc
, pkg
.installed
.Canonical_version (),
443 HMARGIN
, current_col
);
444 for (set
<packageversion
>::iterator i
= pkg
.versions
.begin ();
445 i
!= pkg
.versions
.end (); ++i
)
446 if (*i
!= pkg
.installed
)
447 note_width (headers
, dc
, i
->Canonical_version (),
448 HMARGIN
+ SPIN_WIDTH
, new_col
);
450 if (pkg
.SDesc ().size())
451 s
+= String (": ") + pkg
.SDesc ();
452 note_width (headers
, dc
, s
, HMARGIN
, pkg_col
);
454 if (view_mode
!= PickView::views::Category
&& pkg
.categories
.size () > 2)
456 String
compound_cat("");
457 std::set
<String
, String::caseless
>::const_iterator cat
;
460 for (cnt
= 0, cat
= pkg
.categories
.begin ();
461 cnt
< NUM_CATEGORY_COL_WIDTH
&& cat
!= pkg
.categories
.end ();
464 if (cat
->casecompare ("All") == 0)
466 if (compound_cat
.size ())
467 compound_cat
+= ", ";
468 compound_cat
+= *cat
;
471 note_width (headers
, dc
, compound_cat
, HMARGIN
, cat_col
);
475 // ensure that the new_col is wide enough for all the labels
476 const char *captions
[] = { "Uninstall", "Skip", "Reinstall", "Retrieve",
477 "Source", "Keep", NULL
};
478 for (int i
= 0; captions
[i
]; i
++)
479 note_width (headers
, dc
, captions
[i
], HMARGIN
+ SPIN_WIDTH
, new_col
);
481 // finally, compute the actual x values based on widths
483 for (i
= 1; i
<= last_col
; i
++)
484 headers
[i
].x
= headers
[i
- 1].x
+ headers
[i
- 1].width
;
488 PickView::PickView (Category
&cat
) : deftrust (TRUST_UNKNOWN
),
489 contents (*this, cat
, 0, false, true), showObsolete (false),
490 hasClientRect (false)
495 PickView::init(views _mode
)
497 HDC dc
= GetDC (GetHWND());
498 sysfont
= GetStockObject (DEFAULT_GUI_FONT
);
499 SelectObject (dc
, sysfont
);
500 GetTextMetrics (dc
, &tm
);
502 bitmap_dc
= CreateCompatibleDC (dc
);
503 #define LI(x) LoadImage (hinstance, MAKEINTRESOURCE (x), IMAGE_BITMAP, 0, 0, 0);
504 bm_spin
= LI (IDB_SPIN
);
505 bm_checkyes
= LI (IDB_CHECK_YES
);
506 bm_checkno
= LI (IDB_CHECK_NO
);
507 bm_checkna
= LI (IDB_CHECK_NA
);
508 bm_treeplus
= LI (IDB_TREE_PLUS
);
509 bm_treeminus
= LI (IDB_TREE_MINUS
);
512 row_height
= (tm
.tmHeight
+ tm
.tmExternalLeading
+ ROW_MARGIN
);
513 int irh
= tm
.tmExternalLeading
+ tm
.tmDescent
+ 11 + ROW_MARGIN
;
514 if (row_height
< irh
)
520 // Ensure that the common control DLL is loaded, and then create
521 // the header control.
522 INITCOMMONCONTROLSEX controlinfo
= { sizeof (INITCOMMONCONTROLSEX
),
523 ICC_LISTVIEW_CLASSES
};
524 InitCommonControlsEx (&controlinfo
);
526 if ((listheader
= CreateWindowEx (0, WC_HEADER
, (LPCTSTR
) NULL
,
527 WS_CHILD
| WS_BORDER
| CCS_NORESIZE
|
529 HDS_HORZ
, 0, 0, 0, 0, GetHWND(),
530 (HMENU
) IDC_CHOOSE_LISTHEADER
, hinstance
,
531 (LPVOID
) NULL
)) == NULL
)
532 // FIXME: throw an exception
535 // Retrieve the bounding rectangle of the parent window's
536 // client area, and then request size and position values
537 // from the header control.
538 RECT rcParent
= GetClientRect ();
542 if (!SendMessage (listheader
, HDM_LAYOUT
, 0, (LPARAM
) & hdl
))
543 // FIXME: throw an exception
546 // Set the font of the listheader, but don't redraw, because its not shown
547 // yet.This message does not return a value, so we are not checking it as we
549 SendMessage (listheader
, WM_SETFONT
, (WPARAM
) sysfont
, FALSE
);
551 // Set the size, position, and visibility of the header control.
552 SetWindowPos (listheader
, wp
.hwndInsertAfter
, wp
.x
, wp
.y
,
553 wp
.cx
, wp
.cy
, wp
.flags
| SWP_SHOWWINDOW
);
555 header_height
= wp
.cy
;
556 ReleaseDC (GetHWND (), dc
);
562 PickView::~PickView()
566 bool PickView::registerWindowClass ()
568 if (WindowClassAtom
!= 0)
571 // We're not registered yet
574 wc
.cbSize
= sizeof (wc
);
575 // Some sensible style defaults
576 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
577 // Our default window procedure. This replaces itself
578 // on the first call with the simpler Window::WindowProcReflector().
579 wc
.lpfnWndProc
= Window::FirstWindowProcReflector
;
582 // One pointer to REFLECTION_INFO in the extra window instance bytes
585 wc
.hInstance
= hinstance
; //GetInstance ();
586 // Use a bunch of system defaults for the GUI elements
587 wc
.hIcon
= LoadIcon (0, IDI_APPLICATION
);
589 wc
.hCursor
= LoadCursor (0, IDC_ARROW
);
590 wc
.hbrBackground
= NULL
;
592 wc
.lpszMenuName
= NULL
;
593 // We'll get a little crazy here with the class name
594 wc
.lpszClassName
= "listview";
596 // All set, try to register
597 WindowClassAtom
= RegisterClassEx (&wc
);
598 if (WindowClassAtom
== 0)
599 log (LOG_BABBLE
) << "Failed to register listview " << GetLastError () << endLog
;
600 return WindowClassAtom
!= 0;
604 PickView::list_vscroll (HWND hwnd
, HWND hctl
, UINT code
, int pos
)
606 scroll (hwnd
, SB_VERT
, &scroll_ulc_y
, code
);
611 PickView::list_hscroll (HWND hwnd
, HWND hctl
, UINT code
, int pos
)
613 scroll (hwnd
, SB_HORZ
, &scroll_ulc_x
, code
);
618 PickView::list_click (HWND hwnd
, BOOL dblclk
, int x
, int y
, UINT hitCode
)
622 if (contents
.itemcount () == 0)
625 if (y
< header_height
)
628 y
+= scroll_ulc_y
- header_height
;
630 row
= (y
+ ROW_MARGIN
/ 2) / row_height
;
632 if (row
< 0 || row
>= contents
.itemcount ())
635 refresh
= click (row
, x
);
637 // XXX we need a method to queryt he database to see if more
638 // than just one package has changed! Until then...
643 RECT r
= GetClientRect ();
645 memset (&si
, 0, sizeof (si
));
646 si
.cbSize
= sizeof (si
);
647 si
.fMask
= SIF_ALL
| SIF_DISABLENOSCROLL
; /* SIF_RANGE was giving strange behaviour */
650 si
.nMax
= contents
.itemcount () * row_height
;
651 si
.nPage
= r
.bottom
- header_height
;
653 /* if we are under the minimum display count ,
654 * set the offset to 0
656 if ((unsigned int) si
.nMax
<= si
.nPage
)
658 si
.nPos
= scroll_ulc_y
;
660 SetScrollInfo (GetHWND(), SB_VERT
, &si
, TRUE
);
662 InvalidateRect (GetHWND(), &r
, TRUE
);
669 headers
[new_col
].x
- scroll_ulc_x
;
671 headers
[src_col
+ 1].x
- scroll_ulc_x
;
673 header_height
+ row
* row_height
-
675 rect
.bottom
= rect
.top
+ row_height
;
676 InvalidateRect (hwnd
, &rect
, TRUE
);
684 * PickView::listview_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
687 PickView::WindowProc (UINT message
, WPARAM wParam
, LPARAM lParam
)
695 list_hscroll (GetHWND(), (HWND
)lParam
, LOWORD(wParam
), HIWORD(wParam
));
698 list_vscroll (GetHWND(), (HWND
)lParam
, LOWORD(wParam
), HIWORD(wParam
));
701 // this is how many 'notches' the wheel scrolled, forward/up = positive
702 wheel_notches
= GET_WHEEL_DELTA_WPARAM(wParam
) / 120;
704 // determine how many lines the user has configred for a mouse scroll
705 SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0, &wheel_lines
, 0);
707 if (wheel_lines
== 0) // do no scrolling
709 else if (wheel_lines
== WHEEL_PAGESCROLL
)
710 scroll (GetHWND (), SB_VERT
, &scroll_ulc_y
, (wheel_notches
> 0) ?
711 SB_PAGEUP
: SB_PAGEDOWN
);
713 scroll (GetHWND (), SB_VERT
, &scroll_ulc_y
, (wheel_notches
> 0) ?
714 SB_LINEUP
: SB_LINEDOWN
, wheel_lines
* abs (wheel_notches
));
717 list_click (GetHWND(), FALSE
, LOWORD(lParam
), HIWORD(lParam
), wParam
);
724 // pnmh = (LPNMHDR) lParam
725 LPNMHEADER phdr
= (LPNMHEADER
) lParam
;
726 switch (phdr
->hdr
.code
)
728 case HDN_ITEMCHANGED
:
729 if (phdr
->hdr
.hwndFrom
== ListHeader ())
731 if (phdr
->pitem
&& phdr
->pitem
->mask
& HDI_WIDTH
)
732 headers
[phdr
->iItem
].width
= phdr
->pitem
->cxy
;
734 for (int i
= 1; i
<= last_col
; i
++)
735 headers
[i
].x
= headers
[i
- 1].x
+ headers
[i
- 1].width
;
737 RECT r
= GetClientRect ();
739 si
.cbSize
= sizeof (si
);
740 si
.fMask
= SIF_ALL
| SIF_DISABLENOSCROLL
;
741 GetScrollInfo (GetHWND(), SB_HORZ
, &si
);
743 int oldMax
= si
.nMax
;
744 si
.nMax
= headers
[last_col
].x
+ headers
[last_col
].width
;
745 if (si
.nTrackPos
&& oldMax
> si
.nMax
)
746 si
.nTrackPos
+= si
.nMax
- oldMax
;
749 SetScrollInfo (GetHWND(), SB_HORZ
, &si
, TRUE
);
750 InvalidateRect (GetHWND(), &r
, TRUE
);
751 if (si
.nTrackPos
&& oldMax
> si
.nMax
)
752 scroll (GetHWND(), SB_HORZ
, &scroll_ulc_x
, SB_THUMBTRACK
);
760 // Note: WM_SIZE msgs only appear when 'just' scrolling the window
761 RECT clientRect
= GetWindowRect ();
765 if ((dx
= clientRect
.right
- clientRect
.left
-
766 lastClientRect
.width ()) != 0)
768 headers
[last_col
].width
+= dx
;
770 ::MoveWindow (listheader
, -scroll_ulc_x
, 0,
771 headers
[last_col
].x
+
772 headers
[last_col
].width
, header_height
, TRUE
);
776 hasClientRect
= true;
778 lastClientRect
= clientRect
;
783 // default: can't handle this message
784 return DefWindowProc (GetHWND(), message
, wParam
, lParam
);
788 PickView::paint (HWND hwnd
)
790 // we want to retrieve the update region before calling BeginPaint,
791 // because after we do that the update region is validated and we can
792 // no longer retrieve it
793 HRGN hUpdRgn
= CreateRectRgn (0, 0, 0, 0);
795 if (GetUpdateRgn (hwnd
, hUpdRgn
, FALSE
) == 0)
801 // tell the system that we're going to begin painting our window
802 // it will prevent further WM_PAINT messages from arriving until we're
803 // done, and if any part of our window was invalidated while we are
804 // painting, it will retrigger us so that we can fix it
806 HDC hdc
= BeginPaint (hwnd
, &ps
);
808 SelectObject (hdc
, sysfont
);
809 SetTextColor (hdc
, GetSysColor (COLOR_WINDOWTEXT
));
810 FillRgn (hdc
, hUpdRgn
, GetSysColorBrush(COLOR_WINDOW
));
813 ::GetClientRect (hwnd
, &cr
);
815 int x
= cr
.left
- scroll_ulc_x
;
816 int y
= cr
.top
- scroll_ulc_y
+ header_height
;
818 contents
.paint (hdc
, hUpdRgn
, x
, y
, 0, (view_mode
==
819 PickView::views::Category
) ? 0 : 1);
821 if (contents
.itemcount () == 0)
823 static const char *msg
= "Nothing to Install/Update";
824 if (source
== IDC_SOURCE_DOWNLOAD
)
825 msg
= "Nothing to Download";
826 TextOut (hdc
, x
+ HMARGIN
, y
, msg
, strlen (msg
));
829 DeleteObject (hUpdRgn
);
830 EndPaint (hwnd
, &ps
);
835 PickView::Create (Window
* parent
, DWORD Style
, RECT
*r
)
838 // First register the window class, if we haven't already
839 if (!registerWindowClass ())
841 // Registration failed
845 // Save our parent, we'll probably need it eventually.
848 // Create the window instance
849 CreateWindowEx (// Extended Style
851 // window class atom (name)
852 "listview", //MAKEINTATOM(WindowClassAtom),
853 "listviewwindow", // no title-bar string yet
856 r
? r
->left
: CW_USEDEFAULT
,
857 r
? r
->top
: CW_USEDEFAULT
,
858 r
? r
->right
- r
->left
+ 1 : CW_USEDEFAULT
,
859 r
? r
->bottom
- r
->top
+ 1 : CW_USEDEFAULT
,
861 parent
== NULL
? (HWND
)NULL
: parent
->GetHWND (),
863 (HMENU
) MAKEINTRESOURCE (IDC_CHOOSE_LIST
),
864 // The application instance
866 // The this ptr, which we'll use to set up
867 // the WindowProc reflection.
868 reinterpret_cast<void *>((Window
*)this));
869 if (GetHWND() == NULL
)
871 log (LOG_BABBLE
) << "Failed to create PickView " << GetLastError () << endLog
;
879 PickView::defaultTrust (trusts trust
)
881 this->deftrust
= trust
;
883 for (vector
<packagemeta
*>::iterator i
= db
.packages
.begin ();
884 i
!= db
.packages
.end (); ++i
)
886 packagemeta
& pkg
= **i
;
888 || pkg
.categories
.find ("Base") != pkg
.categories
.end ()
889 || pkg
.categories
.find ("Misc") != pkg
.categories
.end ())
891 pkg
.desired
= pkg
.trustp (trust
);
893 pkg
.desired
.pick (pkg
.desired
.accessible() &&
894 pkg
.desired
!= pkg
.installed
);
897 pkg
.desired
= packageversion ();
899 RECT r
= GetClientRect ();
900 InvalidateRect (this->GetHWND(), &r
, TRUE
);
901 // and then do the same for categories with no packages.
902 for (packagedb::categoriesType::iterator n
= packagedb::categories
.begin();
903 n
!= packagedb::categories
.end(); ++n
)
904 if (!n
->second
.size())
906 log (LOG_BABBLE
) << "Removing empty category " << n
->first
<< endLog
;
907 packagedb::categories
.erase (n
++);
911 /* This recalculates all column widths and resets the view */
915 HDC dc
= GetDC (GetHWND ());
917 // we must set the font of the DC here, otherwise the width calculations
918 // will be off because the system will use the wrong font metrics
919 sysfont
= GetStockObject (DEFAULT_GUI_FONT
);
920 SelectObject (dc
, sysfont
);
922 // init headers for the current mode
926 // save the current mode
927 views cur_view_mode
= view_mode
;
929 // switch to the other type and do those headers
930 view_mode
= (view_mode
== PickView::views::Category
) ?
931 PickView::views::PackageFull
: PickView::views::Category
;
934 ReleaseDC (GetHWND (), dc
);
936 view_mode
= cur_view_mode
;
937 setViewMode (view_mode
);