]> cygwin.com Git - cygwin-apps/setup.git/commitdiff
2005-05-21 Brian Dessent <brian@dessent.net>
authorBrian Dessent <brian@dessent.net>
Sat, 21 May 2005 23:04:03 +0000 (23:04 +0000)
committerBrian Dessent <brian@dessent.net>
Sat, 21 May 2005 23:04:03 +0000 (23:04 +0000)
* prereq.cc: New file.
* prereq.h: Ditto.
* tree-minus.bmp: Ditto.
* tree-plus.bmp: Ditto.
* Makefile.am: Add prereq.cc and prereq.h to build.
* PickCategoryLine.cc (PickCategoryLine::paint): Add new parameter and
refactor.  Use bitmap for '+' and '-' indicators.  Draw package lines
column-wise for better drawing efficiency.
(PickCategoryLine::click): Use previously calculated x value.
* PickCategoryLine.h (PickCategoryLine::paint): Update prototype.  Add
'spin_x' member.
* PickLine.h (PickLine:paint): Update prototype.
* PickPackageLine.cc (PickPackageLine::DrawCheck): Remove.
(PickPackageLine::DrawIcon): New function.
(PickPackageLine::paint): Add parameter.  Refactor completely for more
efficient painting.
* PickPackageLine.h (PickPackageLine::DrawIcon): Add prototype.
(PickPackageLine::paint): Update prototype.
(PickPackageLine::DrawCheck): Remove.
* PickView.cc (pkg_headers): Remove unused 'slen' field, add new
'needs_clip' field to signify if clipping is necessary for this column.
(PickView::note_width): Fold long line.  Refactor slightly for
simplicity.
(PickView::set_view_mode): Remove.
(PickView::cycleViewMode): New function.
(PickView::setViewMode): Refactor completely.  Incorporate functionality
of clear_view() here instead.  Simplify package selection into a single
'for' loop rather than repeating code for each type.
(isObsolete): New function, with second overloaded version.
(PickView::setObsolete): New function.
(PickView::insert_pkg): Do not show obsolete packages.  Move
declaration of 'db' lower.  Fix whitespace.
(PickView::insert_category): Do not show obsolete packages.
(PickView::clear_view): Remove.  Moved logic into 'setViewMode'.
(PickView::scroll): Add additional parameter 'howmany' with default
value of 1.  Scroll by 'howmany' lines for SB_LINEDOWN and SB_LINEUP.
(NUM_CATEGORY_COL_WIDTH): Define.
(PickView::init_headers): Fix whitespace.  Add comments.  Ignore
obsolete packages in width calculations.  Add functionality to size
'Category' column so that at least NUM_CATEGORY_COL_WIDTH categories
are displayed for every package.  Ensure that 'new_col' takes into
account all possible labels.
(PickView::PickView): Initialize showObsolete to false.
(PickView::init): Remove unused bitmap bm_rtarrow.  Add new bitmaps
bm_treeplus and bm_treeminus.  Use a macro for better readability.
Fix whitespace formatting.  Remove header computation from here, call
refresh() instead.
(PickView::registerWindowClass): Remove unnecessary background brush.
(PickView::WindowProc): Add support for WM_MOUSEWHEEL message
processing.  Fix indentation.  Reformat for readability.
(PickView::paint): Get the update region before calling BeginPaint.
Fill the update region with the default colors.  Do not do clipping
here.  Pass update region to the PickLine paint function instead.
Free the update region when finished.
(PickView::Create): Fix indentation.
(PickView::defaultTrust): Ditto.
(PickView::refresh): Add column recalculation logic here.
* PickView.h: Fix indentation.
(RTARROW_WIDTH): Remove unused define.
(NEW_COL_SIZE_SLOP): Ditto.
(TREE_INDENT): Define.
(PickView::get_view_mode): Remove.
(PickView::set_view_mode): Rename to setViewMode for consistency.
(PickView::cycleViewMode): Add new function.
(PickView::setObsolete): Ditto.
(PickView::clear_view): Remove.
(PickView::bm_treeplus): Define new member.
(PickView::bm_treeminus): Ditto.
(PickView::scroll): Add parameter.
(PickView::Header::slen): Remove unused member.
(PickView::Header::needs_clip): Define new member.
(PickView::showObsolete): Ditto.
(isObsolete): Add prototype, and for overloaded version as well.
* choose.cc: Add include.
(ChooserControlsInfo): Allow new checkbox to be resized.
(ChooserPage::OnInit): Start dialog with 'Hide obsolete' checked.
(ChooserPage::OnNext): Call the dependency checker, act accordingly.
(ChooserPage::changeTrust): Notify dependency checker of current trust
level when it changes.
(ChooserPage::OnMessageCmd): Just call cycleViewMode instead when
changing the view.  Update the chooser when the user toggles the
'hide obsolete' checkbox.
(ChooserPage::OnMouseWheel): New function.  Pass mouse wheel message
on to chooser.
* choose.h (OnMouseWheel): Add prototype.
* main.cc: Add include.
(main): Define and initialize the PrereqPage object.  Add it into
the property sheet list.
* PropPage.cc (PropertyPage::DialogProc): Add support for WM_MOUSEWHEEL
message processing in derived classes.
(PropertyPage::OnMouseWheel): New function.
* PropPage.h (PropertyPage::OnMouseWheel): Add prototype.
* res.rc (IDD_LOCAL_DIR): Shorten edit box so that pushbutton is not
crowded.
(IDD_SITE): Provide static text with an ID so that it can be resized
properly.  Move pushbutton slightly to right so that it doesn't crowd
edit box.
(IDD_SPLASH): Change copyright displayed on spash screen to be generic
since the actual list of contributors is long.
(IDD_CHOOSE): Add checkbox.  Resize other controls to accomodate.
(IDD_PREREQ): New dialog.
(SPIN): Delete duplicated bitmap resource.
(IDB_RTARROW): Remove unused bitmap resource.
(IDB_TREE_PLUS): Add.
(IDB_TREE_MINUS): Ditto.
(IDS_TRUSTPREV_TOOLTIP): Revise wording to be more concise.
(IDS_TRUSTCURR_TOOLTIP): Ditto.
(IDS_TRUSTEXP_TOOLTIP): Ditto.
(IDS_VIEWBUTTON_TOOLTIP): Ditto.
* resource.h (IDD_PREREQ): Define.
(IDB_RTARROW): Remove.
(IDB_TREE_PLUS): Add, and renumber.
(IDB_TREE_MINUS): Ditto.
(IDC_SITE_USERURL): Define.
(IDC_CHOOSE_HIDE): Ditto.
(IDC_PREREQ_TEXT): Ditto.
(IDC_PREREQ_EDIT): Ditto.
(IDC_PREREQ_CHECK): Ditto.
* site.cc (SiteControlsInfo): Ensure that 'User URL' static text is
properly resized.

21 files changed:
ChangeLog
Makefile.am
PickCategoryLine.cc
PickCategoryLine.h
PickLine.h
PickPackageLine.cc
PickPackageLine.h
PickView.cc
PickView.h
choose.cc
choose.h
main.cc
prereq.cc [new file with mode: 0644]
prereq.h [new file with mode: 0644]
proppage.cc
proppage.h
res.rc
resource.h
site.cc
tree-minus.bmp [new file with mode: 0755]
tree-plus.bmp [new file with mode: 0755]

index 114660ca4bcb77662ee498a272cd31c267f1c190..8b86d87c31bdd008a9214cce5a306c8cfa92a76f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,126 @@
+2005-05-21  Brian Dessent  <brian@dessent.net>
+
+       * prereq.cc: New file.
+       * prereq.h: Ditto.
+       * tree-minus.bmp: Ditto.
+       * tree-plus.bmp: Ditto.
+       * Makefile.am: Add prereq.cc and prereq.h to build.
+       * PickCategoryLine.cc (PickCategoryLine::paint): Add new parameter and
+       refactor.  Use bitmap for '+' and '-' indicators.  Draw package lines
+       column-wise for better drawing efficiency.
+       (PickCategoryLine::click): Use previously calculated x value.
+       * PickCategoryLine.h (PickCategoryLine::paint): Update prototype.  Add
+       'spin_x' member.
+       * PickLine.h (PickLine:paint): Update prototype.
+       * PickPackageLine.cc (PickPackageLine::DrawCheck): Remove.
+       (PickPackageLine::DrawIcon): New function.
+       (PickPackageLine::paint): Add parameter.  Refactor completely for more
+       efficient painting.
+       * PickPackageLine.h (PickPackageLine::DrawIcon): Add prototype.
+       (PickPackageLine::paint): Update prototype.
+       (PickPackageLine::DrawCheck): Remove.
+       * PickView.cc (pkg_headers): Remove unused 'slen' field, add new 
+       'needs_clip' field to signify if clipping is necessary for this column.
+       (PickView::note_width): Fold long line.  Refactor slightly for 
+       simplicity.
+       (PickView::set_view_mode): Remove.
+       (PickView::cycleViewMode): New function.
+       (PickView::setViewMode): Refactor completely.  Incorporate functionality
+       of clear_view() here instead.  Simplify package selection into a single
+       'for' loop rather than repeating code for each type.
+       (isObsolete): New function, with second overloaded version.
+       (PickView::setObsolete): New function.
+       (PickView::insert_pkg): Do not show obsolete packages.  Move
+       declaration of 'db' lower.  Fix whitespace.
+       (PickView::insert_category): Do not show obsolete packages.
+       (PickView::clear_view): Remove.  Moved logic into 'setViewMode'. 
+       (PickView::scroll): Add additional parameter 'howmany' with default
+       value of 1.  Scroll by 'howmany' lines for SB_LINEDOWN and SB_LINEUP.
+       (NUM_CATEGORY_COL_WIDTH): Define.
+       (PickView::init_headers): Fix whitespace.  Add comments.  Ignore
+       obsolete packages in width calculations.  Add functionality to size
+       'Category' column so that at least NUM_CATEGORY_COL_WIDTH categories
+       are displayed for every package.  Ensure that 'new_col' takes into
+       account all possible labels.
+       (PickView::PickView): Initialize showObsolete to false.
+       (PickView::init): Remove unused bitmap bm_rtarrow.  Add new bitmaps
+       bm_treeplus and bm_treeminus.  Use a macro for better readability.
+       Fix whitespace formatting.  Remove header computation from here, call
+       refresh() instead.
+       (PickView::registerWindowClass): Remove unnecessary background brush.
+       (PickView::WindowProc): Add support for WM_MOUSEWHEEL message
+       processing.  Fix indentation.  Reformat for readability.
+       (PickView::paint): Get the update region before calling BeginPaint.
+       Fill the update region with the default colors.  Do not do clipping
+       here.  Pass update region to the PickLine paint function instead.
+       Free the update region when finished.
+       (PickView::Create): Fix indentation.
+       (PickView::defaultTrust): Ditto.
+       (PickView::refresh): Add column recalculation logic here.
+       * PickView.h: Fix indentation.
+       (RTARROW_WIDTH): Remove unused define.
+       (NEW_COL_SIZE_SLOP): Ditto.
+       (TREE_INDENT): Define.
+       (PickView::get_view_mode): Remove.
+       (PickView::set_view_mode): Rename to setViewMode for consistency.
+       (PickView::cycleViewMode): Add new function.
+       (PickView::setObsolete): Ditto.
+       (PickView::clear_view): Remove.
+       (PickView::bm_treeplus): Define new member.
+       (PickView::bm_treeminus): Ditto.
+       (PickView::scroll): Add parameter.
+       (PickView::Header::slen): Remove unused member.
+       (PickView::Header::needs_clip): Define new member.
+       (PickView::showObsolete): Ditto.
+       (isObsolete): Add prototype, and for overloaded version as well.
+       * choose.cc: Add include.
+       (ChooserControlsInfo): Allow new checkbox to be resized.
+       (ChooserPage::OnInit): Start dialog with 'Hide obsolete' checked.
+       (ChooserPage::OnNext): Call the dependency checker, act accordingly.
+       (ChooserPage::changeTrust): Notify dependency checker of current trust
+       level when it changes.
+       (ChooserPage::OnMessageCmd): Just call cycleViewMode instead when
+       changing the view.  Update the chooser when the user toggles the
+       'hide obsolete' checkbox.
+       (ChooserPage::OnMouseWheel): New function.  Pass mouse wheel message
+       on to chooser.
+       * choose.h (OnMouseWheel): Add prototype.
+       * main.cc: Add include.
+       (main): Define and initialize the PrereqPage object.  Add it into
+       the property sheet list.
+       * PropPage.cc (PropertyPage::DialogProc): Add support for WM_MOUSEWHEEL
+       message processing in derived classes.
+       (PropertyPage::OnMouseWheel): New function.
+       * PropPage.h (PropertyPage::OnMouseWheel): Add prototype.
+       * res.rc (IDD_LOCAL_DIR): Shorten edit box so that pushbutton is not
+       crowded.
+       (IDD_SITE): Provide static text with an ID so that it can be resized
+       properly.  Move pushbutton slightly to right so that it doesn't crowd
+       edit box.
+       (IDD_SPLASH): Change copyright displayed on spash screen to be generic
+       since the actual list of contributors is long.
+       (IDD_CHOOSE): Add checkbox.  Resize other controls to accomodate.
+       (IDD_PREREQ): New dialog.
+       (SPIN): Delete duplicated bitmap resource.
+       (IDB_RTARROW): Remove unused bitmap resource.
+       (IDB_TREE_PLUS): Add.
+       (IDB_TREE_MINUS): Ditto.
+       (IDS_TRUSTPREV_TOOLTIP): Revise wording to be more concise.
+       (IDS_TRUSTCURR_TOOLTIP): Ditto.
+       (IDS_TRUSTEXP_TOOLTIP): Ditto.
+       (IDS_VIEWBUTTON_TOOLTIP): Ditto.
+       * resource.h (IDD_PREREQ): Define.
+       (IDB_RTARROW): Remove.
+       (IDB_TREE_PLUS): Add, and renumber.
+       (IDB_TREE_MINUS): Ditto.
+       (IDC_SITE_USERURL): Define.
+       (IDC_CHOOSE_HIDE): Ditto.
+       (IDC_PREREQ_TEXT): Ditto.
+       (IDC_PREREQ_EDIT): Ditto.
+       (IDC_PREREQ_CHECK): Ditto.
+       * site.cc (SiteControlsInfo): Ensure that 'User URL' static text is
+       properly resized.
+
 2005-05-14  Max Bowsher  <maxb@ukf.net>
 
        "Type" field of packageversions was not even being filled in. Fix.
index 293956b593a0f8351e1945a6fc38e0396da99c94..5fcffe3fdd810e9fc51656cd9bb62af608838d0e 100644 (file)
@@ -232,6 +232,8 @@ setup_SOURCES = \
        PickView.cc \
        PickView.h \
        postinstall.cc \
+       prereq.cc \
+       prereq.h \
        proppage.cc \
        proppage.h \
        propsheet.cc \
index 4a3bacc7c6ccbb5853ade28b8db4c8aa80914d5b..b5472f737c0c3093891b0551beea2b16674a98ed 100644 (file)
@@ -29,41 +29,80 @@ PickCategoryLine::empty (void)
 }
 
 void
-PickCategoryLine::paint (HDC hdc, int x, int y, int row, int show_cat)
+PickCategoryLine::paint (HDC hdc, HRGN hUpdRgn, int x, int y, int row, int show_cat)
 {
   int r = y + row * theView.row_height;
   if (show_label)
     {
-      int by = r + theView.tm.tmHeight - 11;
-      String temp=(String("+ ") +cat.first);
-      TextOut (hdc,
-              x + theView.headers[theView.cat_col].x + HMARGIN / 2 +
-              depth * 8, r, temp.c_str(), temp.size());
+      int x2 = x + theView.headers[theView.cat_col].x + HMARGIN / 2 + depth * TREE_INDENT;
+      int by = r + (theView.tm.tmHeight / 2) - 5;
+
+      // draw the '+' or '-' box
+      SelectObject (theView.bitmap_dc, 
+                      (collapsed ? theView.bm_treeplus : theView.bm_treeminus));
+      BitBlt (hdc, x2, by, 11, 11, theView.bitmap_dc, 0, 0, SRCCOPY);
+
+      // draw the category name
+      TextOut (hdc, x2 + 11 + ICON_MARGIN, r, cat.first.c_str(), cat.first.size());
       if (!labellength)
        {
          SIZE s;
-         GetTextExtentPoint32 (hdc, temp.c_str(), temp.size(), &s);
+         GetTextExtentPoint32 (hdc, cat.first.c_str(), cat.first.size(), &s);
          labellength = s.cx;
        }
+      
+      // draw the 'spin' glyph
       SelectObject (theView.bitmap_dc, theView.bm_spin);
-      BitBlt (hdc,
-             x + theView.headers[theView.cat_col].x +
-             labellength + depth * 8 +
-             ICON_MARGIN +
-             HMARGIN / 2, by, 11, 11, theView.bitmap_dc, 0, 0, SRCCOPY);
-      TextOut (hdc,
-              x + theView.headers[theView.cat_col].x +
-              labellength + depth * 8 +
-              ICON_MARGIN + SPIN_WIDTH +
-              HMARGIN, r, current_default.caption (), strlen (current_default.caption ()));
+      spin_x = x2 + 11 + ICON_MARGIN + labellength + ICON_MARGIN;
+      BitBlt (hdc, spin_x, by, 11, 11, theView.bitmap_dc, 0, 0, SRCCOPY);
+      
+      // draw the caption ('Default', 'Install', etc)
+      TextOut (hdc, spin_x + SPIN_WIDTH + ICON_MARGIN, r, 
+               current_default.caption (), strlen (current_default.caption ()));
+      row++;
     }
   if (collapsed)
     return;
-  int accum_row = row + (show_label ? 1 : 0);
-  for (size_t n = 0; n < bucket.size (); ++n)
+  
+  // are the siblings containers?
+  if (bucket.size () && bucket[0]->IsContainer ())
+    {
+      for (size_t n = 0; n < bucket.size (); n++)
+        {
+          bucket[n]->paint (hdc, hUpdRgn, x, y, row, show_cat);
+          row += bucket[n]->itemcount ();
+        }
+    }
+  else
     {
-      bucket[n]->paint (hdc, x, y, accum_row, show_cat);
-      accum_row += bucket[n]->itemcount ();
+      // calculate the maximum y value we expect for this group of lines
+      int max_y = y + (row + bucket.size ()) * theView.row_height;
+    
+      // paint all contained rows, columnwise
+      for (int i = 0; theView.headers[i].text; i++)
+        {
+          RECT r;
+          r.left = x + theView.headers[i].x;
+          r.right = r.left + theView.headers[i].width;
+    
+          // set up a clipping mask if necessary
+          if (theView.headers[i].needs_clip)
+            IntersectClipRect (hdc, r.left, y, r.right, max_y);
+    
+          // draw each row in this column
+          for (unsigned int n = 0; n < bucket.size (); n++)
+            {
+              // test for visibility
+              r.top = y + ((row + n) * theView.row_height);
+              r.bottom = r.top + theView.row_height;      
+              if (RectVisible (hdc, &r) != 0)
+                bucket[n]->paint (hdc, hUpdRgn, (int)r.left, (int)r.top, i, show_cat);
+            }
+    
+          // restore original clipping area
+          if (theView.headers[i].needs_clip)
+            SelectClipRgn (hdc, hUpdRgn);
+        }
     }
 }
 
@@ -72,8 +111,7 @@ PickCategoryLine::click (int const myrow, int const ClickedRow, int const x)
 {
   if (myrow == ClickedRow && show_label)
     {
-      if ((size_t) x >= theView.headers[theView.cat_col].x +
-         labellength + depth * 8 + ICON_MARGIN + HMARGIN / 2)
+      if ((size_t) x >= spin_x)
        {
          ++current_default;
          
index d72481dcc61a6eee36ef93e9003156d0dc8a3175..dcffbac4c397ce63ba87c1ec71a30e48d3bf16c8 100644 (file)
@@ -52,7 +52,7 @@ public:
     if (!show_label)
       collapsed = false;
   }
-  virtual void paint (HDC hdc, int x, int y, int row, int show_cat);
+  virtual void paint (HDC hdc, HRGN hUpdRgn, int x, int y, int row, int show_cat);
   virtual int click (int const myrow, int const ClickedRow, int const x);
   virtual int itemcount () const
   {
@@ -80,6 +80,7 @@ private:
   bool collapsed;
   bool show_label;
   size_t labellength;
+  size_t spin_x;    // x-coord where the spin button starts
   size_t depth;
   PickCategoryLine (PickCategoryLine const &);
   PickCategoryLine & operator= (PickCategoryLine const &);
index db2f10876880b2faf0c7b23485e1fad61e0ee15c..f4df2ca595ef835cf84fce875a8f3b6504d56a4a 100644 (file)
@@ -22,7 +22,7 @@
 class PickLine
 {
 public:
-  virtual void paint (HDC hdc, int x, int y, int row, int show_cat) = 0;
+  virtual void paint (HDC hdc, HRGN hUpdRgn, int x, int y, int col_num, int show_cat) = 0;
   virtual int click (int const myrow, int const ClickedRow, int const x) = 0;
   virtual int set_action (packagemeta::_actions) = 0;
   virtual int itemcount () const = 0;
index 08dd24a33f0553b45c906b08c79d4622f74a0514..48066c91eb912dbd214e67a3036c8e5be6c53861 100644 (file)
 #include "package_version.h"
 
 void
-PickPackageLine::DrawCheck (int const checked, HDC hdc, int const column, HRGN const clip, int const x, int const by)
+PickPackageLine::DrawIcon (HDC hdc, int x, int y, HANDLE hIcon)
 {
-  HANDLE check_bm;
-  if (checked == 0)
-    check_bm = theView.bm_checkna;
-  else if (checked == 1)
-    check_bm = theView.bm_checkyes;
-  else if (checked == 2)
-    check_bm = theView.bm_checkno;
-  else
-    return;
-  
-  SelectObject (theView.bitmap_dc, check_bm);
-  IntersectClipRect (hdc, x + theView.headers[column].x, by,
-                   x + theView.headers[column].x +
-                   theView.headers[column].width, by + 11);
-  BitBlt (hdc, x + theView.headers[column].x + HMARGIN / 2, by, 11,
-         11, theView.bitmap_dc, 0, 0, SRCCOPY);
-  SelectClipRgn (hdc, clip);
+  SelectObject (theView.bitmap_dc, hIcon);
+  BitBlt (hdc, x, y, 11, 11, theView.bitmap_dc, 0, 0, SRCCOPY);
 }
 
 void
-PickPackageLine::paint (HDC hdc, int x, int y, int row, int show_cat)
+PickPackageLine::paint (HDC hdc, HRGN unused, int x, int y, int col_num, int show_cat)
 {
-  int r = y + row * theView.row_height;
-  int rb = r + theView.tm.tmHeight;
+  int rb = y + theView.tm.tmHeight;
   int by = rb - 11; // top of box images
-  int oldDC = SaveDC (hdc);
-  if (!oldDC)
-    return;
-  HRGN oldClip = CreateRectRgn (0, 0, 0, 0);
-  if (GetRandomRgn (hdc, oldClip, SYSRGN) == -1)
+  String s;
+
+  if (col_num == theView.current_col && pkg.installed)
     {
-      RestoreDC (hdc, oldDC);
-      return;
+      TextOut (hdc, x + HMARGIN/2, y, pkg.installed.Canonical_version ().c_str(),
+               pkg.installed.Canonical_version ().size());
+    }      
+  else if (col_num == theView.new_col)
+    {
+      // TextOut (hdc, x + HMARGIN/2 + NEW_COL_SIZE_SLOP, y, s.c_str(), s.size());
+      // DrawIcon (hdc, x + HMARGIN/2 + ICON_MARGIN/2 + RTARROW_WIDTH, by, theView.bm_spin);
+      TextOut (hdc, x + HMARGIN/2 + ICON_MARGIN/2 + SPIN_WIDTH , y, 
+            pkg.action_caption ().c_str(), pkg.action_caption ().size());
+      DrawIcon (hdc, x + HMARGIN/2, by, theView.bm_spin);
     }
-  HRGN oldClip2;
-  if (IsWindowsNT()) {
-                                 
-  unsigned int regionsize = GetRegionData (oldClip, 0, 0);
-  LPRGNDATA oldClipData = (LPRGNDATA) malloc (regionsize);
-  if (GetRegionData (oldClip, regionsize, oldClipData) > regionsize)
+  else if (col_num == theView.bintick_col)
     {
-      RestoreDC (hdc, oldDC);
-      DeleteObject (oldClip);
-      return;
+      if (/* uninstall or skip */ !pkg.desired ||
+          /* current version */ pkg.desired == pkg.installed ||
+          /* no source */ !pkg.desired.accessible())
+        DrawIcon (hdc, x + HMARGIN/2, by, theView.bm_checkna);
+      else if (pkg.desired.picked())
+        DrawIcon (hdc, x + HMARGIN/2, by, theView.bm_checkyes);
+      else
+        DrawIcon (hdc, x + HMARGIN/2, by, theView.bm_checkno);
     }
-  for (unsigned int n = 0; n < oldClipData->rdh.nCount; n++)
-    for (unsigned int t = 0; t < 2; t++)
-      ScreenToClient (WindowFromDC (hdc),
-                     &((POINT *) oldClipData->Buffer)[t + n * 2]);
+  else if (col_num == theView.srctick_col)
+    {
+      if ( /* uninstall */ !pkg.desired ||
 
-  oldClip2 = ExtCreateRegion (NULL, regionsize, oldClipData);
-                             }
-  else 
-    oldClip2 = oldClip;  
-  
-  SelectClipRgn (hdc, oldClip2);
-  if (pkg.installed)
+#if 0
+          /* note: I'm not sure what the logic here is.  With this following
+             check enabled, clicking on the "source" box for a package that
+             is already installed results it in showing "n/a", instead of a
+             cross-box.  That seems very unintuitive, it should show a cross-
+             box to indicate that the source is going to be downloaded and
+             unpacked.  Disabling this, but leaving the code as reference
+             in case there is some reason I'm missing for having it. --b.d.  */
+          /* source only */ (!pkg.desired.picked()
+                        && pkg.desired.sourcePackage().picked() && pkg.desired == pkg.installed) ||
+#endif
+          /* when no source mirror available */
+          !pkg.desired.sourcePackage().accessible())
+        DrawIcon (hdc, x + HMARGIN/2, by, theView.bm_checkna);
+      else if (pkg.desired.sourcePackage().picked())
+        DrawIcon (hdc, x + HMARGIN/2, by, theView.bm_checkyes);
+      else
+        DrawIcon (hdc, x + HMARGIN/2, by, theView.bm_checkno);   
+    }
+  else if (col_num == theView.cat_col)
     {
-      IntersectClipRect (hdc, x + theView.headers[theView.current_col].x,
-                        r,
-                        x + theView.headers[theView.current_col].x +
-                        theView.headers[theView.current_col].width, rb);
-      TextOut (hdc,
-              x + theView.headers[theView.current_col].x + HMARGIN / 2, r,
-              pkg.installed.Canonical_version ().c_str(),
-              pkg.installed.Canonical_version ().size());
-      SelectObject (theView.bitmap_dc, theView.bm_rtarrow);
-      BitBlt (hdc, x + theView.headers[theView.new_col].x + HMARGIN / 2,
-             by, 11, 11, theView.bitmap_dc, 0, 0, SRCCOPY);
-      SelectClipRgn (hdc, oldClip2);
+      /* shows "first" category - do we want to show any? */
+      if (pkg.categories.size () && show_cat)
+        {
+          s = pkg.getReadableCategoryList();
+          TextOut (hdc, x + HMARGIN / 2, y, s.c_str(), s.size());
+        }
     }
-
-  String s = pkg.action_caption ();
-  IntersectClipRect (hdc, x + theView.headers[theView.new_col].x,
-                    r,
-                    x + theView.headers[theView.new_col].x +
-                    theView.headers[theView.new_col].width, rb);
-  TextOut (hdc,
-          x + theView.headers[theView.new_col].x + HMARGIN / 2 +
-          NEW_COL_SIZE_SLOP, r, s.c_str(), s.size());
-  SelectObject (theView.bitmap_dc, theView.bm_spin);
-  BitBlt (hdc,
-         x + theView.headers[theView.new_col].x + ICON_MARGIN / 2 +
-         RTARROW_WIDTH + HMARGIN / 2, by, 11, 11, theView.bitmap_dc, 0, 0,
-         SRCCOPY);
-  SelectClipRgn (hdc, oldClip2);
-
-  int checked;
-
-  if (/* uninstall or skip */ !pkg.desired ||
-      /* current version */ pkg.desired == pkg.installed ||
-      /* no source */ !pkg.desired.accessible())
-    checked = 0;
-  else if (pkg.desired.picked())
-    checked = 1;
-  else
-    checked = 2;
-      
-  DrawCheck (checked, hdc, theView.bintick_col, oldClip2, x, by);
-  
-  if ( /* uninstall */ !pkg.desired ||
-      /* source only */ (!pkg.desired.picked()
-                        && pkg.desired.sourcePackage().picked() && pkg.desired == pkg.installed) ||
-      /* when no source mirror available */
-      !pkg.desired.sourcePackage().accessible())
-    checked = 0;
-  else if (pkg.desired.sourcePackage().picked())
-    checked = 1;
-  else
-    checked = 2;
-
-  DrawCheck (checked, hdc, theView.srctick_col, oldClip2, x, by);
-
-  /* shows "first" category - do we want to show any? */
-  if (pkg.categories.size () && show_cat)
+  else if (col_num == theView.pkg_col)
     {
-      String catName = pkg.getReadableCategoryList();
-      IntersectClipRect (hdc, x + theView.headers[theView.cat_col].x, r,
-                        x + theView.headers[theView.cat_col].x +
-                        theView.headers[theView.cat_col].width - HMARGIN / 2, rb);
-      TextOut (hdc, x + theView.headers[theView.cat_col].x + HMARGIN / 2, r,
-              catName.c_str(),
-              catName.size());
-      SelectClipRgn (hdc, oldClip2);
+      s = pkg.name;
+      if (pkg.SDesc ().size())
+        s += String(": ") + pkg.SDesc ();
+      TextOut (hdc, x + HMARGIN / 2, y, s.c_str(), s.size());
     }
-
-  s = pkg.name;
-  if (pkg.SDesc ().size())
-    s += String(": ") + pkg.SDesc ();
-  IntersectClipRect (hdc, x + theView.headers[theView.pkg_col].x, r,
-                    x + theView.headers[theView.pkg_col].x +
-                    theView.headers[theView.pkg_col].width, rb);
-  TextOut (hdc, x + theView.headers[theView.pkg_col].x + HMARGIN / 2, r, s.c_str(),
-          s.size());
-  DeleteObject (oldClip);
-  DeleteObject (oldClip2);
-  RestoreDC (hdc, oldDC);
 }
 
 int
index f8537c8c9893e9442de6f27cde810f6577060174..b1571e844ef8950aed2177816252444e818854d8 100644 (file)
@@ -26,7 +26,8 @@ public:
   PickPackageLine (PickView &aView, packagemeta & apkg):PickLine (apkg.key), pkg (apkg), theView (aView)
   {
   };
-  virtual void paint (HDC hdc, int x, int y, int row, int show_cat);
+  void DrawIcon (HDC hdc, int x, int y, HANDLE hIcon);
+  virtual void paint (HDC hdc, HRGN unused, int x, int y, int col_num, int show_cat);
   virtual int click (int const myrow, int const ClickedRow, int const x);
   virtual int itemcount () const
   {
@@ -43,8 +44,6 @@ public:
 private:
   packagemeta & pkg;
   PickView & theView;
-  // XXX make checked an enum or tri-valued class of its own
-  void DrawCheck (int const checked, HDC hdc, int const column, HRGN const clip, int const x, int const by);
 };
 
 #endif /* SETUP_PICKPACKAGELINE_H */
index d1dfdd85955bc53c4097f8986146a4bbab30d92f..6441e6229342c50d132689eb313ab566aad7edda 100644 (file)
 using namespace std;
 
 static PickView::Header pkg_headers[] = {
-  {"Current", 7, 0, 0},
-  {"New", 3, 0, 0},
-  {"Bin?", 4, 0, 0},
-  {"Src?", 4, 0, 0},
-  {"Categories", 10, 0, 0},
-  {"Package", 7, 0, 0},
-  {0, 0, 0, 0}
+  {"Current", 0, 0, true},
+  {"New", 0, 0, true},
+  {"Bin?", 0, 0, false},
+  {"Src?", 0, 0, false},
+  {"Categories", 0, 0, true},
+  {"Package", 0, 0, true},
+  {0, 0, 0, false}
 };
 
 static PickView::Header cat_headers[] = {
-  {"Category", 8, 0, 0},
-  {"Current", 7, 0, 0},
-  {"New", 3, 0, 0},
-  {"Bin?", 4, 0, 0},
-  {"Src?", 4, 0, 0},
-  {"Package", 7, 0, 0},
-  {0, 0, 0, 0}
+  {"Category", 0, 0, true},
+  {"Current", 0, 0, true},
+  {"New", 0, 0, true},
+  {"Bin?", 0, 0, false},
+  {"Src?", 0, 0, false},
+  {"Package", 0, 0, true},
+  {0, 0, 0, false}
 };
 
 // PickView:: views
@@ -82,8 +82,6 @@ DoInsertItem (HWND hwndHeader, int iInsertAfter, int nWidth, LPSTR lpsz)
   return index;
 }
 
-
-
 void
 PickView::set_headers ()
 {
@@ -126,81 +124,70 @@ PickView::set_headers ()
 }
 
 void
-PickView::note_width (PickView::Header *hdrs, HDC dc, String const &string, int addend,
-            int column)
+PickView::note_width (PickView::Header *hdrs, HDC dc, String const &string, 
+                      int addend, int column)
 {
-  if (!string.size())
-    {
-      if (hdrs[column].width < addend)
-        hdrs[column].width = addend;
-      return;
-    }
-  SIZE s;
-  GetTextExtentPoint32 (dc, string.c_str(), string.size(), &s);
+  SIZE s = { 0, 0 };
+
+  if (string.size())
+    GetTextExtentPoint32 (dc, string.c_str(), string.size(), &s);
   if (hdrs[column].width < s.cx + addend)
     hdrs[column].width = s.cx + addend;
 }
 
 void
-PickView::set_view_mode (PickView::views _mode)
+PickView::cycleViewMode ()
 {
-  view_mode = _mode;
-  set_headers ();
+  setViewMode (++view_mode);
 }
 
 void
-PickView::setViewMode (PickView::views mode)
+PickView::setViewMode (views mode)
 {
-  set_view_mode (mode);
-
-  clear_view ();
+  view_mode = mode;
+  set_headers ();
   packagedb db;
-  if (get_view_mode () == PickView::views::Package)
-    {
-      for (vector <packagemeta *>::iterator i = db.packages.begin ();
-    i != db.packages.end (); ++i)
-   {
-    packagemeta & pkg = **i;
-   if ((!pkg.desired && pkg.installed)
-        || (pkg.desired && (pkg.desired.picked () 
-         || pkg.desired.sourcePackage().picked())))
-       insert_pkg (pkg);
-  }
-    }
-  else if (get_view_mode () == PickView::views::PackageKeeps)
-    {
-      for (vector <packagemeta *>::iterator i = db.packages.begin ();
-     i != db.packages.end (); ++i)
-   {
-    packagemeta & pkg = **i;
-   if (pkg.installed && pkg.desired && !pkg.desired.picked() 
-         && !pkg.desired.sourcePackage().picked())
-        insert_pkg (pkg);
-  }
-    }
-  else if (get_view_mode () == PickView::views::PackageSkips)
+
+  contents.empty ();
+  if (view_mode == PickView::views::Category)
     {
-      for (vector <packagemeta *>::iterator i = db.packages.begin ();
-     i != db.packages.end (); ++i)
-   {
-    packagemeta & pkg = **i;
-   if (!pkg.desired && !pkg.installed)
-      insert_pkg (pkg);
-  }
+      contents.ShowLabel (true);
+      /* start collapsed. TODO: make this a chooser flag */
+      for (packagedb::categoriesType::iterator n =
+            packagedb::categories.begin(); n != packagedb::categories.end();
+            ++n)
+        insert_category (&*n, CATEGORY_COLLAPSED);
     }
-  else if (get_view_mode () == PickView::views::PackageFull)
+  else
     {
+      contents.ShowLabel (false);
+      // iterate through every package
       for (vector <packagemeta *>::iterator i = db.packages.begin ();
-      i != db.packages.end (); ++i)
-   insert_pkg (**i);
-    }
-  else if (get_view_mode () == PickView::views::Category)
-    {
-      /* start collapsed. TODO: make this a chooser flag */
-      for (packagedb::categoriesType::iterator n 
-     = packagedb::categories.begin();
-       n != packagedb::categories.end(); ++n)
-  insert_category (&*n, CATEGORY_COLLAPSED);
+            i != db.packages.end (); ++i)
+        {
+          packagemeta & pkg = **i;
+
+          if ( // "Full" : everything
+              (view_mode == PickView::views::PackageFull)
+
+              // "Partial" : packages that are being added/removed/upgraded
+              || (view_mode == PickView::views::Package &&
+                  ((!pkg.desired && pkg.installed) ||         // uninstall
+                    (pkg.desired &&
+                      (pkg.desired.picked () ||               // install bin
+                       pkg.desired.sourcePackage ().picked ())))) // src
+              
+              // "Up to date" : installed packages that will not be changed
+              || (view_mode == PickView::views::PackageKeeps &&
+                  (pkg.installed && pkg.desired && !pkg.desired.picked ()
+                    && !pkg.desired.sourcePackage ().picked ()))
+
+              // "Not installed"
+              || (view_mode == PickView::views::PackageSkips &&
+                  (!pkg.desired && !pkg.installed)))
+            
+            insert_pkg (pkg);
+        }
     }
 
   RECT r = GetClientRect ();
@@ -248,9 +235,42 @@ PickView::views::caption ()
     }
 }
 
+/* meant to be called on packagemeta::categories */
+bool
+isObsolete (set <String, String::caseless> &categories)
+{
+  set <String, String::caseless>::const_iterator i;
+  
+  for (i = categories.begin (); i != categories.end (); ++i)
+    if (isObsolete (*i))
+      return true;
+  return false;
+}
+
+bool
+isObsolete (const String &catname)
+{
+  if (catname.casecompare ("ZZZRemovedPackages") == 0 
+        || catname.casecompare ("_", 1) == 0)
+    return true;
+  return false;
+}
+
+/* Sets the mode for showing/hiding obsolete junk packages.  */
+void
+PickView::setObsolete (bool doit)
+{
+  showObsolete = doit;
+  refresh ();
+}
+
+
 void
 PickView::insert_pkg (packagemeta & pkg)
 {
+  if (!showObsolete && isObsolete (pkg.categories))
+    return;
+  
   if (view_mode != views::Category)
     {
       PickLine & line = *new PickPackageLine (*this, pkg);
@@ -261,13 +281,13 @@ PickView::insert_pkg (packagemeta & pkg)
       for (set <String, String::caseless>::const_iterator x
           = pkg.categories.begin (); x != pkg.categories.end (); ++x)
         {
-         packagedb db;
          // Special case - yuck
          if (x->casecompare ("All") == 0)
            continue;
 
+         packagedb db;
          PickCategoryLine & catline = 
-           *new PickCategoryLine (*this,db.categories.find (*x), 1);
+           *new PickCategoryLine (*this, *db.categories.find (*x), 1);
          PickLine & line = *new PickPackageLine(*this, pkg);
          catline.insert (line);
          contents.insert (catline);
@@ -276,10 +296,11 @@ PickView::insert_pkg (packagemeta & pkg)
 }
 
 void
-PickView::insert_category (Category * cat, bool collapsed)
+PickView::insert_category (Category *cat, bool collapsed)
 {
   // Urk, special case
-  if (cat->first.casecompare ("All") == 0)
+  if (cat->first.casecompare ("All") == 0 ||
+      (!showObsolete && isObsolete (cat->first)))
     return;
   PickCategoryLine & catline = *new PickCategoryLine (*this, *cat, 1, collapsed);
   for (vector <packagemeta *>::iterator i = cat->second.begin ();
@@ -291,21 +312,6 @@ PickView::insert_category (Category * cat, bool collapsed)
   contents.insert (catline);
 }
 
-void
-PickView::clear_view (void)
-{
-  contents.empty ();
-  if (view_mode == views::Unknown)
-    return;
-  if (view_mode == views::PackageFull ||
-      view_mode == views::Package ||
-      view_mode == views::PackageKeeps ||
-      view_mode == views::PackageSkips)
-    contents.ShowLabel (false);
-  else if (view_mode == views::Category)
-    contents.ShowLabel ();
-}
-
 PickView::views&
 PickView::views::operator++ ()
 {
@@ -323,7 +329,7 @@ PickView::click (int row, int x)
 
 
 void
-PickView::scroll (HWND hwnd, int which, int *var, int code)
+PickView::scroll (HWND hwnd, int which, int *var, int code, int howmany = 1)
 {
   SCROLLINFO si;
   si.cbSize = sizeof (si);
@@ -344,10 +350,10 @@ PickView::scroll (HWND hwnd, int which, int *var, int code)
       si.nPos = 0;
       break;
     case SB_LINEDOWN:
-      si.nPos += row_height;
+      si.nPos += (row_height * howmany);
       break;
     case SB_LINEUP:
-      si.nPos -= row_height;
+      si.nPos -= (row_height * howmany);
       break;
     case SB_PAGEDOWN:
       si.nPos += si.nPage * 9 / 10;
@@ -392,6 +398,10 @@ PickView::scroll (HWND hwnd, int which, int *var, int code)
   UpdateWindow (hwnd);
 }
 
+/* this means to make the 'category' column wide enough to fit the first 'n'
+   categories for each package.  */
+#define NUM_CATEGORY_COL_WIDTH 2
+
 void
 PickView::init_headers (HDC dc)
 {
@@ -403,36 +413,72 @@ PickView::init_headers (HDC dc)
       headers[i].x = 0;
     }
 
-  for (i = 0; headers[i].text; i++)
-    note_width (headers, dc, headers[i].text, HMARGIN, i);
-  /* src checkbox */
+  // accomodate widths of the 'bin' and 'src' checkbox columns
   note_width (headers, dc, 0, HMARGIN + 11, bintick_col);
   note_width (headers, dc, 0, HMARGIN + 11, srctick_col);
+  
+  // accomodate the width of each category name
   packagedb db;
   for (packagedb::categoriesType::iterator n = packagedb::categories.begin();
        n != packagedb::categories.end(); ++n)
-    note_width (headers, dc, String ("+ ")+n->first, HMARGIN, cat_col);
+    {
+      if (!showObsolete && isObsolete (n->first))
+        continue;
+      note_width (headers, dc, n->first, HMARGIN, cat_col);
+    }
+
+  /* For each package, accomodate the width of the installed version in the
+     current_col, the widths of all other versions in the new_col, and the
+     width of the sdesc for the pkg_col.  Also, if this is not a Category
+     view, adjust the 'category' column so that the first NUM_CATEGORY_COL_WIDTH
+     categories from each package fits.  */
   for (vector <packagemeta *>::iterator n = db.packages.begin ();
        n != db.packages.end (); ++n)
     {
       packagemeta & pkg = **n;
+      if (!showObsolete && isObsolete (pkg.categories))
+        continue;
       if (pkg.installed)
         note_width (headers, dc, pkg.installed.Canonical_version (),
                     HMARGIN, current_col);
-      for (set<packageversion>::iterator i=pkg.versions.begin();
-          i != pkg.versions.end(); ++i)
+      for (set<packageversion>::iterator i = pkg.versions.begin ();
+          i != pkg.versions.end (); ++i)
         if (*i != pkg.installed)
-          note_width (headers, dc,
-                      i->Canonical_version (),
-                      NEW_COL_SIZE_SLOP + HMARGIN, new_col);
+          note_width (headers, dc, i->Canonical_version (), 
+                      HMARGIN + SPIN_WIDTH, new_col);
       String s = pkg.name;
       if (pkg.SDesc ().size())
        s += String (": ") + pkg.SDesc ();
       note_width (headers, dc, s, HMARGIN, pkg_col);
+      
+      if (view_mode != PickView::views::Category && pkg.categories.size () > 2)
+        {
+          String compound_cat("");          
+          std::set<String, String::caseless>::const_iterator cat;
+          size_t cnt;
+          
+          for (cnt = 0, cat = pkg.categories.begin (); 
+               cnt < NUM_CATEGORY_COL_WIDTH && cat != pkg.categories.end ();
+               ++cat)
+            {
+              if (cat->casecompare ("All") == 0)
+                continue;
+              if (compound_cat.size ())
+                compound_cat += ", ";
+              compound_cat += *cat;
+              cnt++;
+            }
+          note_width (headers, dc, compound_cat, HMARGIN, cat_col);
+        }
     }
-  note_width (headers, dc, "keep", NEW_COL_SIZE_SLOP + HMARGIN, new_col);
-  note_width (headers, dc, "uninstall", NEW_COL_SIZE_SLOP + HMARGIN, new_col);
-
+  
+  // ensure that the new_col is wide enough for all the labels
+  const char *captions[] = { "Uninstall", "Skip", "Reinstall", "Retrieve", 
+                             "Source", "Keep", NULL };
+  for (int i = 0; captions[i]; i++)
+    note_width (headers, dc, captions[i], HMARGIN + SPIN_WIDTH, new_col);
+
+  // finally, compute the actual x values based on widths
   headers[0].x = 0;
   for (i = 1; i <= last_col; i++)
     headers[i].x = headers[i - 1].x + headers[i - 1].width;
@@ -440,7 +486,8 @@ PickView::init_headers (HDC dc)
 
 
 PickView::PickView (Category &cat) : deftrust (TRUST_UNKNOWN),
-contents (*this, cat, 0, false, true), hasClientRect (false)
+contents (*this, cat, 0, false, true), showObsolete (false), 
+hasClientRect (false)
 {
 }
 
@@ -453,26 +500,17 @@ PickView::init(views _mode)
   GetTextMetrics (dc, &tm);
 
   bitmap_dc = CreateCompatibleDC (dc);
-  bm_spin = LoadImage (hinstance, MAKEINTRESOURCE (IDB_SPIN), IMAGE_BITMAP, 0, 0, 0);
-  bm_rtarrow = LoadImage (hinstance, MAKEINTRESOURCE (IDB_RTARROW), IMAGE_BITMAP,
-                              0, 0, 0);
-
-  bm_checkyes = LoadImage (hinstance, MAKEINTRESOURCE (IDB_CHECK_YES), IMAGE_BITMAP,
-                               0, 0, 0);
-  bm_checkno = LoadImage (hinstance, MAKEINTRESOURCE (IDB_CHECK_NO), IMAGE_BITMAP,
-                              0, 0, 0);
-  bm_checkna = LoadImage (hinstance, MAKEINTRESOURCE (IDB_CHECK_NA), IMAGE_BITMAP,
-                              0, 0, 0);
+#define LI(x) LoadImage (hinstance, MAKEINTRESOURCE (x), IMAGE_BITMAP, 0, 0, 0);
+  bm_spin = LI (IDB_SPIN);
+  bm_checkyes = LI (IDB_CHECK_YES);
+  bm_checkno = LI (IDB_CHECK_NO);
+  bm_checkna = LI (IDB_CHECK_NA);
+  bm_treeplus = LI (IDB_TREE_PLUS);
+  bm_treeminus = LI (IDB_TREE_MINUS);  
+#undef LI  
 
   row_height = (tm.tmHeight + tm.tmExternalLeading + ROW_MARGIN);
-  int
-    irh =
-    tm.
-    tmExternalLeading +
-    tm.
-    tmDescent +
-    11 +
-    ROW_MARGIN;
+  int irh = tm.tmExternalLeading + tm.tmDescent + 11 + ROW_MARGIN;
   if (row_height < irh)
     row_height = irh;
 
@@ -481,9 +519,8 @@ PickView::init(views _mode)
 
   // Ensure that the common control DLL is loaded, and then create
   // the header control.
-  INITCOMMONCONTROLSEX controlinfo =
-  {
-  sizeof (INITCOMMONCONTROLSEX), ICC_LISTVIEW_CLASSES};
+  INITCOMMONCONTROLSEX controlinfo = { sizeof (INITCOMMONCONTROLSEX), 
+                                       ICC_LISTVIEW_CLASSES };
   InitCommonControlsEx (&controlinfo);
 
   if ((listheader = CreateWindowEx (0, WC_HEADER, (LPCTSTR) NULL,
@@ -516,18 +553,10 @@ PickView::init(views _mode)
                 wp.cx, wp.cy, wp.flags | SWP_SHOWWINDOW);
 
   header_height = wp.cy;
-
-  view_mode = PickView::views::Package;
-  set_headers ();
-  init_headers (dc);
-  view_mode = PickView::views::Category;
-  set_headers ();
-  init_headers (dc);
+  ReleaseDC (GetHWND (), dc);
 
   view_mode = _mode;
-  set_headers ();
-
-  ReleaseDC (GetHWND(), dc);
+  refresh ();
 }
 
 PickView::~PickView()
@@ -558,7 +587,7 @@ bool PickView::registerWindowClass ()
   wc.hIcon = LoadIcon (0, IDI_APPLICATION);
   wc.hIconSm = NULL;
   wc.hCursor = LoadCursor (0, IDC_ARROW);
-  wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
+  wc.hbrBackground = NULL;
   // No menu
   wc.lpszMenuName = NULL;
   // We'll get a little crazy here with the class name
@@ -657,6 +686,9 @@ PickView::list_click (HWND hwnd, BOOL dblclk, int x, int y, UINT hitCode)
 LRESULT
 PickView::WindowProc (UINT message, WPARAM wParam, LPARAM lParam)
 {
+  int wheel_notches;
+  UINT wheel_lines;
+  
   switch (message)
     {
     case WM_HSCROLL:
@@ -665,6 +697,22 @@ PickView::WindowProc (UINT message, WPARAM wParam, LPARAM lParam)
     case WM_VSCROLL:
       list_vscroll (GetHWND(), (HWND)lParam, LOWORD(wParam), HIWORD(wParam));
       return 0;
+    case WM_MOUSEWHEEL:
+      // this is how many 'notches' the wheel scrolled, forward/up = positive
+      wheel_notches = GET_WHEEL_DELTA_WPARAM(wParam) / 120;
+      
+      // determine how many lines the user has configred for a mouse scroll
+      SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &wheel_lines, 0);
+
+      if (wheel_lines == 0)   // do no scrolling
+        return 0;
+      else if (wheel_lines == WHEEL_PAGESCROLL)
+        scroll (GetHWND (), SB_VERT, &scroll_ulc_y, (wheel_notches > 0) ?
+                SB_PAGEUP : SB_PAGEDOWN);
+      else
+        scroll (GetHWND (), SB_VERT, &scroll_ulc_y, (wheel_notches > 0) ?
+                SB_LINEUP : SB_LINEDOWN, wheel_lines * abs (wheel_notches));
+      return 0; // handled
     case WM_LBUTTONDOWN:
       list_click (GetHWND(), FALSE, LOWORD(lParam), HIWORD(lParam), wParam);
       return 0;
@@ -673,103 +721,112 @@ PickView::WindowProc (UINT message, WPARAM wParam, LPARAM lParam)
       return 0;
     case WM_NOTIFY:
       {
- // pnmh = (LPNMHDR) lParam
- LPNMHEADER phdr = (LPNMHEADER) lParam;
- switch (phdr->hdr.code)
-      {
-      case HDN_ITEMCHANGED:
-        if (phdr->hdr.hwndFrom == ListHeader ())
-        {
-        if (phdr->pitem && phdr->pitem->mask & HDI_WIDTH)
-        headers[phdr->iItem].width = phdr->pitem->cxy;
-      for (int i = 1; i <= last_col; i++)
-         headers[i].x =
-          headers[i - 1].x + headers[i - 1].width;
-     RECT r = GetClientRect ();
-        SCROLLINFO si;
-     si.cbSize = sizeof (si);
-       si.fMask = SIF_ALL | SIF_DISABLENOSCROLL;
-      GetScrollInfo (GetHWND(), SB_HORZ, &si);
-        int oldMax = si.nMax;
-      si.nMax =
-        headers[last_col].x +
-        headers[last_col].width;
-       if (si.nTrackPos && oldMax > si.nMax)
-        si.nTrackPos += si.nMax - oldMax;
-        si.nPage = r.right;
-        SetScrollInfo (GetHWND(), SB_HORZ, &si, TRUE);
-      InvalidateRect (GetHWND(), &r, TRUE);
-       if (si.nTrackPos && oldMax > si.nMax)
-        scroll (GetHWND(), SB_HORZ, &scroll_ulc_x,
-                 SB_THUMBTRACK);
-       }
-        break;
-   default:
-     break;
-   }
-      }
+        // pnmh = (LPNMHDR) lParam
+        LPNMHEADER phdr = (LPNMHEADER) lParam;
+        switch (phdr->hdr.code)
+          {
+          case HDN_ITEMCHANGED:
+            if (phdr->hdr.hwndFrom == ListHeader ())
+              {
+                if (phdr->pitem && phdr->pitem->mask & HDI_WIDTH)
+                  headers[phdr->iItem].width = phdr->pitem->cxy;
+  
+                for (int i = 1; i <= last_col; i++)
+                  headers[i].x = headers[i - 1].x + headers[i - 1].width;
+  
+                RECT r = GetClientRect ();
+                SCROLLINFO si;
+                si.cbSize = sizeof (si);
+                si.fMask = SIF_ALL | SIF_DISABLENOSCROLL;
+                GetScrollInfo (GetHWND(), SB_HORZ, &si);
+  
+                int oldMax = si.nMax;
+                si.nMax = headers[last_col].x + headers[last_col].width;
+                if (si.nTrackPos && oldMax > si.nMax)
+                  si.nTrackPos += si.nMax - oldMax;
+  
+                si.nPage = r.right;
+                SetScrollInfo (GetHWND(), SB_HORZ, &si, TRUE);
+                InvalidateRect (GetHWND(), &r, TRUE);
+                if (si.nTrackPos && oldMax > si.nMax)
+                  scroll (GetHWND(), SB_HORZ, &scroll_ulc_x, SB_THUMBTRACK);
+              }
+            break;
+          }
+        }
+      break;
     case WM_SIZE:
       {
         // Note: WM_SIZE msgs only appear when 'just' scrolling the window
-       RECT clientRect = GetWindowRect ();
-       if (hasClientRect)
-         {
-           int dx = clientRect.right - clientRect.left - lastClientRect.width();
-           if (dx != 0)
-             {
-               headers[last_col].width += dx;
-               
-               set_headers ();
-               
-               ::MoveWindow (listheader, -scroll_ulc_x, 0,
-                           headers[last_col].x +
-                           headers[last_col].width, header_height, TRUE);
-             }
-         }
-         else
-           hasClientRect = true;
-       lastClientRect = clientRect;
-       return 0;
+        RECT clientRect = GetWindowRect ();
+        if (hasClientRect)
+          {
+            int dx;
+            if ((dx = clientRect.right - clientRect.left -
+                        lastClientRect.width ()) != 0)
+              {
+                headers[last_col].width += dx;
+                set_headers ();
+                ::MoveWindow (listheader, -scroll_ulc_x, 0,
+                            headers[last_col].x +
+                            headers[last_col].width, header_height, TRUE);
+              }
+          }
+        else
+          hasClientRect = true;
+  
+        lastClientRect = clientRect;
+        return 0;     
       }
-      
-    default:
-      return DefWindowProc (GetHWND(), message, wParam, lParam);
     }
+  
+  // default: can't handle this message
+  return DefWindowProc (GetHWND(), message, wParam, lParam);
 }
 
 void
 PickView::paint (HWND hwnd)
 {
-  HDC hdc;
-  PAINTSTRUCT ps;
-  int x, y;
+  // we want to retrieve the update region before calling BeginPaint,
+  // because after we do that the update region is validated and we can
+  // no longer retrieve it
+  HRGN hUpdRgn = CreateRectRgn (0, 0, 0, 0);
 
-  hdc = BeginPaint (hwnd, &ps);
+  if (GetUpdateRgn (hwnd, hUpdRgn, FALSE) == 0)
+    {
+      // error?
+      return;
+    }
 
+  // tell the system that we're going to begin painting our window
+  // it will prevent further WM_PAINT messages from arriving until we're
+  // done, and if any part of our window was invalidated while we are
+  // painting, it will retrigger us so that we can fix it
+  PAINTSTRUCT ps;
+  HDC hdc = BeginPaint (hwnd, &ps);
   SelectObject (hdc, sysfont);
-  SetBkColor (hdc, GetSysColor (COLOR_WINDOW));
   SetTextColor (hdc, GetSysColor (COLOR_WINDOWTEXT));
+  FillRgn (hdc, hUpdRgn, GetSysColorBrush(COLOR_WINDOW));
 
   RECT cr;
   ::GetClientRect (hwnd, &cr);
 
-  x = cr.left - scroll_ulc_x;
-  y = cr.top - scroll_ulc_y + header_height;
-
-  IntersectClipRect (hdc, cr.left, cr.top + header_height, cr.right,
-             cr.bottom);
+  int x = cr.left - scroll_ulc_x;
+  int y = cr.top - scroll_ulc_y + header_height;
 
-  contents.paint (hdc, x, y, 0, (get_view_mode () ==
-                     PickView::views::Category) ? 0 : 1);
+  contents.paint (hdc, hUpdRgn, x, y, 0, (view_mode == 
+                                  PickView::views::Category) ? 0 : 1);
 
   if (contents.itemcount () == 0)
     {
       static const char *msg = "Nothing to Install/Update";
       if (source == IDC_SOURCE_DOWNLOAD)
-  msg = "Nothing to Download";
+        msg = "Nothing to Download";
       TextOut (hdc, x + HMARGIN, y, msg, strlen (msg));
     }
 
+  DeleteObject (hUpdRgn);
   EndPaint (hwnd, &ps);
 }
 
@@ -785,27 +842,29 @@ PickView::Create (Window * parent, DWORD Style, RECT *r)
       return false;
     }
 
-    // Save our parent, we'll probably need it eventually.
+  // Save our parent, we'll probably need it eventually.
   setParent(parent);
 
   // Create the window instance
-  CreateWindowEx (
-                   // Extended Style
-                   WS_EX_CLIENTEDGE,
-                   "listview",   //MAKEINTATOM(WindowClassAtom),     // window class atom (name)
-                   "listviewwindow", // no title-bar string yet
-                // Style bits
+  CreateWindowEx (// Extended Style
+                  WS_EX_CLIENTEDGE,
+                  // window class atom (name)
+                  "listview",   //MAKEINTATOM(WindowClassAtom),
+                  "listviewwindow", // no title-bar string yet
+                  // Style bits
                   Style,
-                 r ? r->left : CW_USEDEFAULT, r ? r->top : CW_USEDEFAULT, 
-                 r? r->right - r->left + 1 : CW_USEDEFAULT, 
-                 r? r->bottom - r->top + 1 :CW_USEDEFAULT,
-                   // Parent Window 
-                  parent == NULL ? (HWND) NULL : parent->GetHWND (),
-                   // use class menu 
-                (HMENU) MAKEINTRESOURCE (IDC_CHOOSE_LIST),
-                  // The application instance 
-                   GetInstance (),
-                // The this ptr, which we'll use to set up the WindowProc reflection.
+                  r ? r->left : CW_USEDEFAULT,
+                  r ? r->top : CW_USEDEFAULT,
+                  r ? r->right - r->left + 1 : CW_USEDEFAULT,
+                  r ? r->bottom - r->top + 1 : CW_USEDEFAULT,
+                  // Parent Window
+                  parent == NULL ? (HWND)NULL : parent->GetHWND (),
+                  // use class menu
+                  (HMENU) MAKEINTRESOURCE (IDC_CHOOSE_LIST),
+                  // The application instance
+                  GetInstance (),
+                  // The this ptr, which we'll use to set up
+                  // the WindowProc reflection.
                   reinterpret_cast<void *>((Window *)this));
   if (GetHWND() == NULL)
     {
@@ -826,16 +885,16 @@ PickView::defaultTrust (trusts trust)
     {
       packagemeta & pkg = **i;
       if (pkg.installed
-     || pkg.categories.find ("Base") != pkg.categories.end ()
-   || pkg.categories.find ("Misc") != pkg.categories.end ())
-    {
-    pkg.desired = pkg.trustp (trust);
-      if (pkg.desired)
-     pkg.desired.pick (pkg.desired.accessible() 
-                      && pkg.desired != pkg.installed);
-    }
+            || pkg.categories.find ("Base") != pkg.categories.end ()
+            || pkg.categories.find ("Misc") != pkg.categories.end ())
+        {
+          pkg.desired = pkg.trustp (trust);
+          if (pkg.desired)
+            pkg.desired.pick (pkg.desired.accessible() && 
+                                  pkg.desired != pkg.installed);
+        }
       else
-   pkg.desired = packageversion ();
+        pkg.desired = packageversion ();
     }
   RECT r = GetClientRect ();
   InvalidateRect (this->GetHWND(), &r, TRUE);
@@ -844,13 +903,36 @@ PickView::defaultTrust (trusts trust)
        n != packagedb::categories.end(); ++n)
     if (!n->second.size())
       {
-    log (LOG_BABBLE) << "Removing empty category " << n->first << endLog;
+        log (LOG_BABBLE) << "Removing empty category " << n->first << endLog;
         packagedb::categories.erase (n++);
       }
 }
 
+/* This recalculates all column widths and resets the view */
 void
 PickView::refresh()
 {
-  setViewMode (get_view_mode ());
+  HDC dc = GetDC (GetHWND ());
+  
+  // we must set the font of the DC here, otherwise the width calculations
+  // will be off because the system will use the wrong font metrics
+  sysfont = GetStockObject (DEFAULT_GUI_FONT);
+  SelectObject (dc, sysfont);
+
+  // init headers for the current mode
+  set_headers ();
+  init_headers (dc);
+  
+  // save the current mode
+  views cur_view_mode = view_mode;
+  
+  // switch to the other type and do those headers
+  view_mode = (view_mode == PickView::views::Category) ? 
+                    PickView::views::PackageFull : PickView::views::Category;
+  set_headers ();
+  init_headers (dc);
+  ReleaseDC (GetHWND (), dc);
+
+  view_mode = cur_view_mode;
+  setViewMode (view_mode);
 }
index 0e8a42d55029504d959183685b263b527a620900..8009350837f1ab381ffe1ebbea03ad4348cdcd38 100644 (file)
 #include "window.h"
 #include "RECTWrapper.h"
 
-#define HMARGIN 10
+#define HMARGIN         10
 #define ROW_MARGIN      5
 #define ICON_MARGIN     4
-#define RTARROW_WIDTH 11
-#define SPIN_WIDTH 11
-#define NEW_COL_SIZE_SLOP (ICON_MARGIN + SPIN_WIDTH + RTARROW_WIDTH)
+#define SPIN_WIDTH      11
 #define CHECK_SIZE      11
+#define TREE_INDENT     12
 
 #define CATEGORY_EXPANDED  0
 #define CATEGORY_COLLAPSED 1
@@ -44,13 +43,9 @@ public:
   class views;
   class Header;
   int num_columns;
-  views get_view_mode ()
-  {
-    return view_mode;
-  };
   void defaultTrust (trusts trust);
-  void set_view_mode (views _mode);
-  void setViewMode (PickView::views mode);
+  void cycleViewMode ();
+  void setViewMode (views mode);
   void paint (HWND hwnd);
   LRESULT CALLBACK list_click (HWND hwnd, BOOL dblclk, int x, int y, UINT hitCode);
   LRESULT CALLBACK list_hscroll (HWND hwnd, HWND hctl, UINT code, int pos);
@@ -61,9 +56,9 @@ public:
   void init(views _mode);
   ~PickView();
   const char *mode_caption ();
+  void setObsolete (bool doit);
   void insert_pkg (packagemeta &);
   void insert_category (Category *, bool);
-  void clear_view (void);
   int click (int row, int x);
   void refresh();
   int current_col;
@@ -76,13 +71,13 @@ public:
   int row_height;
   TEXTMETRIC tm;
   HDC bitmap_dc;
-  HANDLE bm_spin,bm_rtarrow, bm_checkyes, bm_checkno, bm_checkna;
+  HANDLE bm_spin, bm_checkyes, bm_checkno, bm_checkna, bm_treeplus, bm_treeminus;
   trusts deftrust;
   HANDLE sysfont;
   int scroll_ulc_x, scroll_ulc_y;
   int header_height;
   PickCategoryLine contents;
-  void scroll (HWND hwnd, int which, int *var, int code);
+  void scroll (HWND hwnd, int which, int *var, int code, int howmany);
   HWND ListHeader (void) const
   {
     return listheader;
@@ -126,15 +121,16 @@ public:
   {
   public:
     const char *text;
-    int slen;
     int width;
     int x;
+    bool needs_clip;
   };
 
 private:
   static ATOM WindowClassAtom;
   HWND listheader;
   views view_mode;
+  bool showObsolete;
 
   // Stuff needed to handle resizing
   bool hasClientRect;
@@ -146,4 +142,7 @@ private:
       int column);
 };
 
+bool isObsolete (std::set <String, String::caseless> &categories);
+bool isObsolete (const String &catname);
+
 #endif /* SETUP_PICKVIEW_H */
index a3740ce07e9f53555742334025af630a37ef6a68..1b5ec44425ba72a243c6a2464ece1321df6b07d7 100644 (file)
--- a/choose.cc
+++ b/choose.cc
@@ -56,6 +56,7 @@ static const char *cvsid =
 #include "threebar.h"
 #include "Generic.h"
 #include "ControlAdjuster.h"
+#include "prereq.h"
 
 using namespace std;
 
@@ -73,6 +74,7 @@ static ControlAdjuster::ControlInfo ChooserControlsInfo[] = {
   {IDC_LISTVIEW_POS,           CP_RIGHT,   CP_TOP},
   {IDC_CHOOSE_VIEWCAPTION,     CP_RIGHT,   CP_TOP},
   {IDC_CHOOSE_LIST,            CP_STRETCH, CP_STRETCH},
+  {IDC_CHOOSE_HIDE,             CP_LEFT,    CP_BOTTOM},
   {0, CP_LEFT, CP_TOP}
 };
 
@@ -147,6 +149,8 @@ ChooserPage::getDefaultListViewSize()
 void
 ChooserPage::OnInit ()
 {
+  CheckDlgButton (GetHWND (), IDC_CHOOSE_HIDE, BST_CHECKED);
+
   if (source == IDC_SOURCE_DOWNLOAD || source == IDC_SOURCE_CWD)
     packagemeta::ScanDownloadedFiles ();
 
@@ -188,17 +192,26 @@ ChooserPage::OnNext ()
   logResults();
 #endif
 
-  if (source == IDC_SOURCE_CWD)
+  PrereqChecker p;
+  if (p.isMet ())
     {
-      // Next, install
-      Progress.SetActivateTask (WM_APP_START_INSTALL);
+      if (source == IDC_SOURCE_CWD)
+        {
+          // Next, install
+          Progress.SetActivateTask (WM_APP_START_INSTALL);
+        }
+      else
+        {
+          // Next, start download from internet
+          Progress.SetActivateTask (WM_APP_START_DOWNLOAD);
+        }
+      return IDD_INSTATUS;
     }
   else
     {
-      // Next, start download from internet
-      Progress.SetActivateTask (WM_APP_START_DOWNLOAD);
+      // rut-roh, some required things are not selected
+      return IDD_PREREQ;
     }
-  return IDD_INSTATUS;
 }
 
 long
@@ -232,6 +245,8 @@ ChooserPage::changeTrust(trusts aTrust)
   for_each (db.packages.begin (), db.packages.end (),
             bind2nd (mem_fun (&packagemeta::set_requirements), aTrust));
   chooser->refresh();
+  PrereqChecker p;
+  p.setTrust (aTrust);
 }
 
 bool
@@ -266,13 +281,16 @@ ChooserPage::OnMessageCmd (int id, HWND hwndctl, UINT code)
       break;
 
     case IDC_CHOOSE_VIEW:
-      chooser->setViewMode (++chooser->get_view_mode ());
+      chooser->cycleViewMode ();
       if (!SetDlgItemText
         (GetHWND (), IDC_CHOOSE_VIEWCAPTION, chooser->mode_caption ()))
       log (LOG_BABBLE) << "Failed to set View button caption " << 
            GetLastError () << endLog;
       break;
       
+    case IDC_CHOOSE_HIDE:
+      chooser->setObsolete (!IsButtonChecked (id));
+      break;
     default:
       // Wasn't recognized or handled.
       return false;
@@ -281,3 +299,9 @@ ChooserPage::OnMessageCmd (int id, HWND hwndctl, UINT code)
   // Was handled since we never got to default above.
   return true;
 }
+
+BOOL CALLBACK
+ChooserPage::OnMouseWheel (UINT message, WPARAM wParam, LPARAM lParam)
+{
+  return chooser->WindowProc (message, wParam, lParam);
+}
index d9b26e0ee08fcda2f50800d6a66fc70498fb2bc9..644a7a685448328d5dd98516d4a653a11e972079 100644 (file)
--- a/choose.h
+++ b/choose.h
@@ -31,6 +31,8 @@ public:
   };
 
   virtual bool OnMessageCmd (int id, HWND hwndctl, UINT code);
+  virtual BOOL CALLBACK OnMouseWheel (UINT message, WPARAM wParam,
+                                     LPARAM lParam);
 
   bool Create ();
   virtual void OnInit ();
diff --git a/main.cc b/main.cc
index 669dd6190489015ac15ffe070c61a1758f837041..68937d5bf7d7af70ac767279703b9da66e8bd0a9 100644 (file)
--- a/main.cc
+++ b/main.cc
@@ -57,6 +57,7 @@ static const char *cvsid =
 #include "net.h"
 #include "site.h"
 #include "choose.h"
+#include "prereq.h"
 #include "threebar.h"
 #include "desktop.h"
 
@@ -461,6 +462,7 @@ main (int argc, char **argv)
     NetPage Net;
     SitePage Site;
     ChooserPage Chooser;
+    PrereqPage Prereq;
     DesktopSetupPage Desktop;
     PropSheet MainWindow;
 
@@ -494,6 +496,7 @@ main (int argc, char **argv)
     Net.Create ();
     Site.Create ();
     Chooser.Create ();
+    Prereq.Create ();
     Progress.Create ();
     Desktop.Create ();
 
@@ -506,6 +509,7 @@ main (int argc, char **argv)
     MainWindow.AddPage (&Net);
     MainWindow.AddPage (&Site);
     MainWindow.AddPage (&Chooser);
+    MainWindow.AddPage (&Prereq);
     MainWindow.AddPage (&Progress);
     MainWindow.AddPage (&Desktop);
 
diff --git a/prereq.cc b/prereq.cc
new file mode 100644 (file)
index 0000000..8404d46
--- /dev/null
+++ b/prereq.cc
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2005 Brian Dessent
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     A copy of the GNU General Public License can be found at
+ *     http://www.gnu.org/
+ *
+ * Written by Brian Dessent <brian@dessent.net>
+ *
+ */
+
+#if 0
+static const char *cvsid =
+  "\n%%% $Id$\n";
+#endif
+
+#include "win32.h"
+#include <commctrl.h>
+#include <stdio.h>
+#include <io.h>
+#include <ctype.h>
+#include <process.h>
+
+#include "prereq.h"
+#include "dialog.h"
+#include "resource.h"
+#include "state.h"
+#include "propsheet.h"
+#include "threebar.h"
+#include "Generic.h"
+#include "LogSingleton.h"
+#include "ControlAdjuster.h"
+#include "package_db.h"
+#include "package_meta.h"
+#include "msg.h"
+
+// Sizing information.
+static ControlAdjuster::ControlInfo PrereqControlsInfo[] = {
+  {IDC_PREREQ_CHECK,           CP_LEFT,    CP_BOTTOM},
+  {IDC_PREREQ_EDIT,            CP_STRETCH, CP_STRETCH},
+  {0, CP_LEFT, CP_TOP}
+};
+
+extern ThreeBarProgressPage Progress;
+
+// ---------------------------------------------------------------------------
+// implements class PrereqPage
+// ---------------------------------------------------------------------------
+
+PrereqPage::PrereqPage ()
+{
+  sizeProcessor.AddControlInfo (PrereqControlsInfo);
+}  
+
+bool
+PrereqPage::Create ()
+{
+  return PropertyPage::Create (IDD_PREREQ);
+}
+
+void
+PrereqPage::OnInit ()
+{
+  // start with the checkbox set
+  CheckDlgButton (GetHWND (), IDC_PREREQ_CHECK, BST_CHECKED);
+  
+  // set the edit-area to a larger font
+  SetDlgItemFont(IDC_PREREQ_EDIT, "MS Shell Dlg", 10);
+}
+
+void
+PrereqPage::OnActivate()
+{
+  // if we have gotten this far, then PrereqChecker has already run isMet
+  // and found that there were missing packages; so we can just call 
+  // getUnmetString to format the results and display it
+  
+  String s;
+  PrereqChecker p;
+  p.getUnmetString (s);
+  SetDlgItemText (GetHWND (), IDC_PREREQ_EDIT, s.c_str ());
+
+  SetFocus (GetDlgItem (IDC_PREREQ_CHECK));
+}
+
+long
+PrereqPage::OnNext ()
+{
+  HWND h = GetHWND ();
+
+  if (!IsDlgButtonChecked (h, IDC_PREREQ_CHECK))
+    {
+      // breakage imminent!  danger, danger
+      int res = MessageBox (h, 
+          "If you continue without correcting the listed conflicts, your "
+          "Cygwin installation will not function properly.\r\n"
+          "We strongly recommend that you let Setup install the listed packages.\r\n\r\n"
+          "Are you sure you want to proceed?",
+          "WARNING - Required Packages Not Selected",
+          MB_YESNO | MB_ICONEXCLAMATION | MB_DEFBUTTON2);
+      if (res == IDNO)
+        return -1;
+      else
+        log (LOG_PLAIN) << 
+            "NOTE!  User refused suggested missing dependencies!  "
+            "Expect some packages to give errors or not function at all." << endLog;
+    }
+  else
+    {
+      // add the missing requirements
+      PrereqChecker p;
+      p.selectMissing ();
+    }
+  if (source == IDC_SOURCE_CWD)
+    {
+      // Next, install
+      Progress.SetActivateTask (WM_APP_START_INSTALL);
+    }
+  else
+    {
+      // Next, start download from internet
+      Progress.SetActivateTask (WM_APP_START_DOWNLOAD);
+    }
+  return IDD_INSTATUS;
+}
+
+long
+PrereqPage::OnBack ()
+{
+  return IDD_CHOOSE;
+}
+
+
+// ---------------------------------------------------------------------------
+// implements class PrereqChecker
+// ---------------------------------------------------------------------------
+
+// instantiate the static members
+map <packagemeta *, vector <packagemeta *>, packagemeta_ltcomp> PrereqChecker::unmet;
+trusts PrereqChecker::theTrust = TRUST_CURR;
+
+/* This function builds a list of unmet dependencies to present to the user on
+   the PrereqPage propsheet.  The data is stored as an associative map of
+   unmet[missing-package] = vector of packages that depend on missing-package */
+bool
+PrereqChecker::isMet ()
+{
+  packagedb db;
+  bool foundUnmet = false;
+
+  // unmet is static - clear it each time this is called
+  unmet.clear ();
+  
+  // loop through each package
+  for (vector <packagemeta *>::iterator n = db.packages.begin ();
+        n != db.packages.end (); ++n)
+    {
+      // if the package is installed or selected to be installed...
+      if ((*n)->desired)
+        {
+          // loop through each dependency
+          for (vector <vector <PackageSpecification *> *>::iterator i = 
+                (*n)->desired.depends ()->begin ();
+                i != (*n)->desired.depends ()->end (); ++i)
+            {
+              // XXX: the following assumes that there is only a single
+              // node in each OR clause, which is currently the case.
+              // if setup is ever pushed to use AND/OR in "depends:"
+              // lines this will have to be updated
+              PackageSpecification *spec = (*i)->at(0);
+                  
+              packagemeta *pack = db.findBinary (*spec);
+              if (!pack)
+                continue;  // asking for a package that doesn't exist - error?
+
+              if (pack->desired && spec->satisfies (pack->desired))
+                {
+                  // dependency met
+                }
+              else
+                {                  
+                  foundUnmet = true;
+                  unmet[pack].push_back (*n);
+                }
+            }
+        }
+    }
+    
+  return !foundUnmet;
+}
+
+/* Formats 'unmet' as a string for display to the user.  */
+void
+PrereqChecker::getUnmetString (String &s)
+{
+  s = "";
+  
+  map <packagemeta *, vector <packagemeta *>, packagemeta_ltcomp>::iterator i;
+  for (i = unmet.begin(); i != unmet.end(); i++)
+    {
+      s = s + "Package: " + i->first->name + "\r\n\tRequired by: ";
+      for (unsigned int j = 0; j < i->second.size(); j++)
+        {
+          s += i->second[j]->name;
+          if (j != i->second.size() - 1)
+            s += ", ";
+        }
+      s += "\r\n\r\n";
+    }
+}
+
+/* Takes the keys of 'unmet' and selects them, using the current trust.  */
+void
+PrereqChecker::selectMissing ()
+{
+  packagedb db;
+
+  // provide a default, even though this should have been set for us
+  if (!theTrust)
+    theTrust = TRUST_CURR;    
+  
+  // get each of the keys of 'unmet'
+  map <packagemeta *, vector <packagemeta *>, packagemeta_ltcomp>::iterator i;
+  for (i = unmet.begin(); i != unmet.end(); i++)
+    {
+      packageversion vers = i->first->trustp (theTrust);
+      i->first->desired = vers;
+      vers.sourcePackage ().pick (false);
+      
+      if (vers == i->first->installed)
+        {
+          vers.pick (false);
+          log (LOG_PLAIN) << "Adding required dependency " << i->first->name <<
+               ": Selecting already-installed version " <<
+               i->first->installed.Canonical_version () << "." << endLog;
+        }
+      else
+        {
+          vers.pick (vers.accessible ());
+          log (LOG_PLAIN) << "Adding required dependency " << i->first->name <<
+              ": Selecting version " << vers.Canonical_version () <<
+              " for installation." << endLog;
+        }
+    }
+}
diff --git a/prereq.h b/prereq.h
new file mode 100644 (file)
index 0000000..cd3f344
--- /dev/null
+++ b/prereq.h
@@ -0,0 +1,55 @@
+#ifndef SETUP_PREREQ_H
+#define SETUP_PREREQ_H
+
+#include <map>
+#include "proppage.h"
+#include "PackageTrust.h"
+#include "package_meta.h"
+
+using namespace std;
+
+// keeps the map sorted by name
+struct packagemeta_ltcomp
+{
+  bool operator() ( const packagemeta *m1, const packagemeta *m2 )
+    { return m1->name.casecompare (m2->name) < 0; }
+};
+
+
+class PrereqPage:public PropertyPage
+{
+public:
+  PrereqPage ();
+  virtual ~PrereqPage () { };
+  bool Create ();
+  virtual void OnInit ();
+  virtual void OnActivate ();
+  virtual long OnNext ();
+  virtual long OnBack ();
+  virtual long OnUnattended () { return 0; };
+};
+
+class PrereqChecker
+{
+public:
+  // checks all dependecies, populates 'unmet'
+  // returns true if unsatisfied dependencies exist
+  bool isMet ();
+  
+  // formats 'unmet' as a string for display
+  void getUnmetString (String &s);
+  
+  // selects/picks the needed packages that were missing
+  void selectMissing ();
+  
+  // notes the current trust (for use in selectMissing)
+  void setTrust (trusts t) { theTrust = t; };
+
+private:
+  
+  // this is the actual hash_map that does all the work
+  static map <packagemeta *, vector <packagemeta *>, packagemeta_ltcomp> unmet;
+  static trusts theTrust;
+};
+
+#endif /* SETUP_PREREQ_H */
index cd87b67d33b8681de82466647e3ed5148ca5586d..4663538c4f8c9367b343d7d4b2e896f3d916430e 100644 (file)
@@ -340,6 +340,14 @@ PropertyPage::DialogProc (UINT message, WPARAM wParam, LPARAM lParam)
           // cast this brush as a BOOL and return it (?!)
           return (BOOL)theURL->second.brush;
         }
+      case WM_MOUSEWHEEL:
+        // we do this so that derived classes that wish to process this message
+        // do not need to reimplement the entire WinProc, they can just
+        // provice an OnMouseWheel.  (Note that mousewheel events are delivered
+        // to the parent of the window that received the scroll, so it would
+        // not work to just process this message there.)
+        return OnMouseWheel (message, wParam, lParam);
+        break;
       default:
         break;
     }
@@ -356,6 +364,12 @@ PropertyPage::DialogProc (UINT message, WPARAM wParam, LPARAM lParam)
   return FALSE;
 }
 
+BOOL CALLBACK
+PropertyPage::OnMouseWheel (UINT message, WPARAM wParam, LPARAM lParam)
+{
+  return 1; // not handled; define in a derived class to support this
+}
+
 void
 PropertyPage::setTitleFont ()
 {
index 49515d2f2c52a81a33ac2598f5bf84139c5344df..302edf03d274b79a21e55aca6d6d8062f0438ca9 100644 (file)
@@ -81,6 +81,8 @@ protected:
   
     virtual BOOL CALLBACK DialogProc (UINT message, WPARAM wParam,
                                      LPARAM lParam);
+    virtual BOOL CALLBACK OnMouseWheel (UINT message, WPARAM wParam,
+                                     LPARAM lParam);
 
 public:
     PropertyPage ();
diff --git a/res.rc b/res.rc
index 8e9c5758127ef4e58eb07dbeda29e9a175ad851f..050090a7ce76aea52e13efb9b28e9948d249dc08 100644 (file)
--- a/res.rc
+++ b/res.rc
@@ -80,7 +80,7 @@ BEGIN
                     317,1
 
     GROUPBOX        "Local Package Directory",IDC_LOCALDIR_GRP,53,67,210,45
-    EDITTEXT        IDC_LOCAL_DIR,58,83,165,15,ES_AUTOHSCROLL | WS_GROUP
+    EDITTEXT        IDC_LOCAL_DIR,58,83,161,15,ES_AUTOHSCROLL | WS_GROUP
     PUSHBUTTON      "B&rowse...",IDC_LOCAL_DIR_BROWSE,223,83,34,14
 END
 
@@ -150,8 +150,8 @@ BEGIN
                     8,NOT WS_GROUP
     EDITTEXT        IDC_EDIT_USER_URL,65,160,185,14,ES_AUTOHSCROLL | 
                     WS_GROUP
-    LTEXT           "User URL:",IDC_STATIC,15,162,45,8,NOT WS_GROUP
-    PUSHBUTTON      "Add",IDC_BUTTON_ADD_URL,250,160,50,14
+    LTEXT           "User URL:",IDC_SITE_USERURL,15,162,45,8,NOT WS_GROUP
+    PUSHBUTTON      "Add",IDC_BUTTON_ADD_URL,255,160,50,14
 END
 
 IDD_NET DIALOG DISCARDABLE  0, 0, 317, 179
@@ -265,8 +265,7 @@ BEGIN
                     "necessary.",IDC_SPLASH_TEXT,115,25,195,90
     ICON            IDI_CYGWIN,IDC_SPLASH_ICON,114,114,21,20,WS_GROUP
     LTEXT           "Version (unknown)",IDC_VERSION,115,137,195,10
-    LTEXT           "Copyright 2000-2005 Red Hat Inc.",IDC_SPLASH_COPYR,
-                    115,150,195,8
+    LTEXT           "Copyright 2000-2005",IDC_SPLASH_COPYR,115,150,195,8
     LTEXT           "http://www.cygwin.com/",IDC_SPLASH_URL,115,162,90,8
 END
 
@@ -324,7 +323,9 @@ BEGIN
     CONTROL         "",IDC_HEADSEPARATOR,"Static",SS_BLACKFRAME | SS_SUNKEN,0,28,
                     317,1
     CONTROL         "",IDC_LISTVIEW_POS,"Static",SS_BLACKFRAME | NOT 
-                    WS_VISIBLE,7,45,303,134
+                    WS_VISIBLE,7,45,303,122
+    CONTROL         "&Hide obsolete packages",IDC_CHOOSE_HIDE,"Button",
+                    BS_AUTOCHECKBOX | WS_TABSTOP,7,167,100,14
     ICON            IDI_CYGWIN,IDC_HEADICON,290,0,21,20
     LTEXT           "Select the packages you want setup to install.",
                     IDC_CHOOSE_INST_TEXT,21,9,239,16,NOT WS_GROUP
@@ -333,6 +334,28 @@ BEGIN
     LTEXT           "",IDC_CHOOSE_VIEWCAPTION,270,33,40,10
 END
 
+IDD_PREREQ DIALOG DISCARDABLE  0, 0, 317, 179
+STYLE DS_MODALFRAME | DS_3DLOOK | WS_CHILD | WS_VISIBLE | WS_CAPTION | 
+    WS_SYSMENU
+CAPTION "Cygwin Setup - Resolve Dependencies"
+FONT 8, "MS Shell Dlg"
+BEGIN
+    CONTROL         "",IDC_HEADSEPARATOR,"Static",SS_BLACKFRAME | SS_SUNKEN,
+                    0,28,317,1
+    ICON            IDI_CYGWIN,IDC_HEADICON,290,0,21,20
+    LTEXT           "Warning!  Unmet Dependencies Found",IDC_STATIC_HEADER_TITLE
+                    ,7,0,258,8,NOT WS_GROUP
+    LTEXT           "The following packages are required but have not been "
+                    "selected.",IDC_STATIC,21,9,239,16,NOT WS_GROUP
+    CONTROL         "&Install these packages to meet dependencies (RECOMMENDED)"
+                    ,IDC_PREREQ_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+                    7,167,225,14
+    EDITTEXT        IDC_PREREQ_EDIT,7,41,303,124,WS_VSCROLL | WS_HSCROLL |
+                    ES_LEFT | ES_MULTILINE | ES_READONLY | ES_AUTOHSCROLL |
+                    ES_AUTOVSCROLL
+
+END
+
 /////////////////////////////////////////////////////////////////////////////
 //
 // Manifest
@@ -361,12 +384,12 @@ CYGWIN.ICON             FILE    DISCARDABLE     "cygwin.ico"
 // Bitmap
 //
 
-SPIN                    BITMAP  DISCARDABLE     "choose-spin.bmp"
 IDB_SPIN                BITMAP  DISCARDABLE     "choose-spin.bmp"
-IDB_RTARROW             BITMAP  DISCARDABLE     "choose-rtarrow.bmp"
 IDB_CHECK_YES           BITMAP  DISCARDABLE     "check-yes.bmp"
 IDB_CHECK_NO            BITMAP  DISCARDABLE     "check-no.bmp"
 IDB_CHECK_NA            BITMAP  DISCARDABLE     "check-na.bmp"
+IDB_TREE_PLUS           BITMAP  DISCARDABLE     "tree-plus.bmp"
+IDB_TREE_MINUS          BITMAP  DISCARDABLE     "tree-minus.bmp"
 
 /////////////////////////////////////////////////////////////////////////////
 //
@@ -403,31 +426,27 @@ BEGIN
     IDS_TRUSTKEEP_TOOLTIP   "Sets all packages to their currently installed "
        "version.  This is equivalent to telling setup not to make any "
        "changes to any package."
-    IDS_TRUSTPREV_TOOLTIP   "Tells setup to try to select the version "
-       "marked as 'Prev' for every package.  'Prev' generally means the "
-       "package that was last considered stable prior to the current stable "
-       "version."
-    IDS_TRUSTCURR_TOOLTIP   "Tells setup to try to select the version for "
-       "each package that is currently considered the most stable.  "
-       "(RECOMMENDED)"
-    IDS_TRUSTEXP_TOOLTIP    "Tells setup to try to select the most recent "
-       "version for every package, even if that version is marked as "
-       "Experimental or for test use by its maintainer."
+    IDS_TRUSTPREV_TOOLTIP   "Globally select the version marked as 'Prev', "
+       "which generally means the version that was last considered stable "
+       "prior to the current stable version."
+    IDS_TRUSTCURR_TOOLTIP   "Globally select the version that is currently "
+       "considered the most stable. (RECOMMENDED)"
+    IDS_TRUSTEXP_TOOLTIP    "Globally select the most recent version, even if "
+       "that version is considered Experimental or for test use by the maintainer."
     IDS_VIEWBUTTON_TOOLTIP  "Cycles the package view.  This determines "
        "which packages are shown in the chooser below.\r\n"
        "\r\n"
-       "Category: Shows packages by heirarchy.  Click on '+' to expand a "
-       "category.\r\n"
+       "Category: Group by package category.  Click on '+' to expand.\r\n"
        "\r\n"
-       "Full: Shows all packages.\r\n"
+       "Full: Show all packages.\r\n"
        "\r\n"
-       "Partial: Shows only packages that are about to be installed, "
-       "removed, or upgraded.  This essentially tells you everything that "
-       "setup is about to change when you press 'Next'.\r\n"
+       "Partial: Show only packages that are about to be installed, removed, "
+       "or upgraded.  This tells you everything that setup is about to change "
+       "when you press 'Next'.\r\n"
        "\r\n"
-       "Up To Date: Shows installed packages that need no action because "
-       "they are at the desired version already.\r\n"
+       "Up To Date: Show installed packages that need no action because they "
+       "are at the desired version already.\r\n"
        "\r\n"
-       "Not installed: Shows packages that are are not currently installed "
+       "Not installed: Show packages that are are not currently installed "
        "and haven't been selected for installation."
 END
index 3e0dabf65f9845892643685b9510b07f895f3eb1..c0668694a0e7ffa959f98cc0943c742857dd4fc5 100644 (file)
 #define IDD_S_POSTINSTALL                 217
 #define IDD_VIRUS                         218
 #define IDD_DESKTOP                       219
+#define IDD_PREREQ                        220
 
 // Bitmaps
 
 #define IDB_SPIN                          300
-#define IDB_RTARROW                       301
-#define IDB_CHECK_YES                     302
-#define IDB_CHECK_NO                      303
-#define IDB_CHECK_NA                      304
+#define IDB_CHECK_YES                     301
+#define IDB_CHECK_NO                      302
+#define IDB_CHECK_NA                      303
+#define IDB_TREE_PLUS                     304
+#define IDB_TREE_MINUS                    305
 
 // icons
 
 #define IDC_SPLASH_TEXT                   571
 #define IDC_SPLASH_ICON                   572
 #define IDC_SPLASH_COPYR                  573
+#define IDC_SITE_USERURL                  574
+#define IDC_CHOOSE_HIDE                   575
+#define IDC_PREREQ_TEXT                   576
+#define IDC_PREREQ_EDIT                   577
+#define IDC_PREREQ_CHECK                  578
diff --git a/site.cc b/site.cc
index 88f76c26c3a6fdcffd4c1d5f682542a9fe3eb9f2..00264ffd13ee9afcaa17442c05c21ad7f6b39abe 100644 (file)
--- a/site.cc
+++ b/site.cc
@@ -53,6 +53,7 @@ static ControlAdjuster::ControlInfo SiteControlsInfo[] = {
   {IDC_URL_LIST,               CP_STRETCH, CP_STRETCH},
   {IDC_EDIT_USER_URL,          CP_STRETCH, CP_BOTTOM},
   {IDC_BUTTON_ADD_URL,         CP_RIGHT,   CP_BOTTOM},
+  {IDC_SITE_USERURL,            CP_LEFT,    CP_BOTTOM},
   {0, CP_LEFT, CP_TOP}
 };
 
diff --git a/tree-minus.bmp b/tree-minus.bmp
new file mode 100755 (executable)
index 0000000..35b2221
Binary files /dev/null and b/tree-minus.bmp differ
diff --git a/tree-plus.bmp b/tree-plus.bmp
new file mode 100755 (executable)
index 0000000..e0335d9
Binary files /dev/null and b/tree-plus.bmp differ
This page took 0.098273 seconds and 5 git commands to generate.