home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C++ / Applications / Nuntius 1.2 / src / Nuntius / UGroupListView.cp < prev    next >
Encoding:
Text File  |  1994-04-12  |  11.6 KB  |  511 lines  |  [TEXT/MPS ]

  1. // Copyright © 1992 Peter Speck, speck@dat.ruc.dk. All rights reserved.
  2. // UGroupListView.cp
  3.  
  4. #include "UGroupListView.h"
  5. #include "UGroupListCmds.h"
  6. #include "UGroupListDoc.h"
  7. #include "UGroupList.h"
  8. #include "UNewsAppl.h"
  9. #include "UGroupDocCmds.h"
  10. #include "UPrefsDatabase.h"
  11. #include "Tools.h"
  12. #include "UThread.h"
  13.  
  14. #include <RsrcGlobals.h>
  15.  
  16. #include <Packages.h>
  17.  
  18. #pragma segment MyGroupList
  19.  
  20. TGroupListView::TGroupListView()
  21. {
  22. }
  23.  
  24. pascal void TGroupListView::Initialize()
  25. {
  26.     inherited::Initialize();
  27.     fWindow = nil;
  28.     fGroupList = nil;
  29.     fDoc = nil;
  30.     fLastTypeKeyTick = 0;
  31. }
  32.  
  33. pascal void TGroupListView::ReadFields(TStream *aStream)
  34. {
  35.     inherited::ReadFields(aStream);
  36. }
  37.  
  38. pascal void TGroupListView::DoPostCreate(TDocument *itsDocument)
  39. {
  40.     inherited::DoPostCreate(itsDocument);
  41.     fWindow = GetWindow();
  42.     fDoc = (TGroupListDoc*) itsDocument;
  43.     fGroupList = fDoc->GetGroupList();
  44. #if qDebug
  45.     if (!IsObject(fDoc))
  46.         ProgramBreak("fDoc is not object");
  47.     if (!IsObject(fGroupList))
  48.         ProgramBreak("fGroupList is not object");
  49. #endif
  50.     StandardGridViewTextStyle gvts;
  51.     gPrefs->GetTextStylePrefs('TSgl', gvts.fTextStyle);
  52.     CalcStandardGridViewFont(gvts);
  53.     fGridViewTextStyle = gvts;
  54. }
  55.  
  56. pascal void TGroupListView::Free()
  57. {
  58.     inherited::Free();
  59. }
  60.  
  61. pascal void TGroupListView::Close()
  62. {
  63.     inherited::Close();
  64. }
  65.  
  66. pascal void TGroupListView::ShowReverted()
  67. {
  68.     SetEmptySelection(kHighlight);
  69.     UpdateList();
  70. }
  71.  
  72. void TGroupListView::ChangedFont()
  73. {
  74.     StandardGridViewTextStyle gvts = fGridViewTextStyle;
  75.     CalcStandardGridViewFont(gvts);
  76.     fGridViewTextStyle = gvts;
  77.     if (fNumOfRows)
  78.         SetRowHeight(1, fNumOfRows, fGridViewTextStyle.fRowHeight);
  79.     Focus();
  80.     ForceRedraw();
  81. }
  82.  
  83. void TGroupListView::AddGroup(CStr255 &name)
  84. {
  85.     if (!fGroupList->AppendGroup(name))
  86.         return;
  87.     InsRowLast(1, fGridViewTextStyle.fRowHeight);
  88.     fDoc->Changed(cGroupListChange, this);
  89. }
  90.  
  91. pascal void TGroupListView::DrawRangeOfCells(GridCell startCell,
  92.                                          GridCell stopCell,
  93.                                          const VRect &aRect)
  94. {
  95.     TextStyle itsTextStyle = fGridViewTextStyle.fTextStyle;
  96.     SetPortTextStyle(itsTextStyle);
  97.     inherited::DrawRangeOfCells(startCell, stopCell, aRect);
  98. }
  99.  
  100. pascal void TGroupListView::DrawCell(GridCell aCell, const VRect &aRect)
  101. {
  102.     CRect r;
  103.     ViewToQDRect(aRect, r);
  104.     short h = r.left + fGridViewTextStyle.fHorzOffset;
  105.     short v = r.top + fGridViewTextStyle.fVertOffset - 1;
  106.     MoveTo(r.left + fGridViewTextStyle.fHorzOffset, r.top + fGridViewTextStyle.fVertOffset - 1);
  107.     CStr255 dotName;
  108.     fGroupList->GetGroupAt(aCell.v, dotName);
  109.     NewArticleStat stat = fGroupList->GetNewArticleStat(aCell.v);
  110.     short id;
  111.     switch (stat)
  112.     {
  113.         case kUnknown:
  114.             id = kGroupListNAUnknown;
  115.             break;
  116.         
  117.         case kNoNew:
  118.             id = kGroupListNANoNew;
  119.             break;
  120.         
  121.         case kHasNew:
  122.             id = kGroupListNAHasNew;
  123.             break;
  124.         
  125.         default:
  126. #if qDebug
  127.             fprintf(stderr, "TGroupListView::DrawCell: Bad NewArticleStat = %ld\n", long(stat));
  128.             ProgramBreak(gEmptyString);
  129. #endif
  130.             id = kGroupListNAUnknown;
  131.             break;
  132.     }
  133.     CStr255 statString;
  134.     MyGetIndString(statString, id);
  135.     MoveTo(h, v);
  136.     DrawString(statString);
  137.     MoveTo(h + 2 * fGridViewTextStyle.fHorzOffset, v);
  138.     DrawString(dotName);
  139. }
  140.  
  141. void TGroupListView::GetCellTextRect(GridCell aCell, CRect &r)
  142. {
  143.     Focus();
  144.     TextStyle itsTextStyle = fGridViewTextStyle.fTextStyle;
  145.     SetPortTextStyle(itsTextStyle);
  146.     VRect vr;
  147.     CellToVRect(aCell, vr);
  148.     ViewToQDRect(vr, r);
  149.     CStr255 text;
  150.     fGroupList->GetGroupAt(aCell.v, text);
  151.     r.left += 3 * fGridViewTextStyle.fHorzOffset - 1;
  152.     r.top += 1;
  153.     r.right = r.left + StringWidth(text) + 2;
  154.     r.bottom -= 1;
  155. }
  156.  
  157. void TGroupListView::HighlighOneCell(GridCell aCell, HLState fromHL, HLState toHL)
  158. {
  159.     CRect r;
  160.     GetCellTextRect(aCell, r);
  161.     PenNormal();
  162.     UseSelectionColor();
  163.     switch (fromHL + toHL)
  164.     {
  165.         case hlOffDim:
  166.             PenMode(patXor);
  167.             FrameRect(r);
  168.             break;
  169.  
  170.         case hlOnDim:
  171.             r.Inset(CPoint(1, 1));
  172.             InvertRect(r);
  173.             break;
  174.  
  175.         case hlOffOn:
  176.             InvertRect(r);
  177.             break;
  178.     }
  179. }
  180.  
  181. pascal void TGroupListView::HighlightCells(RgnHandle theCells,
  182.                                       HLState fromHL,
  183.                                       HLState toHL)
  184. {
  185.     if (fromHL == toHL)
  186.         return;
  187.     Focus();
  188.     switch (fromHL + toHL)
  189.     {
  190.         case hlOffDim:
  191.         case hlOnDim:
  192.         case hlOffOn:
  193.             {
  194.                 CCellInRegionIterator iter(this, theCells);
  195.                 for (GridCell aCell = iter.FirstCell(); iter.More(); aCell = iter.NextCell())
  196.                     HighlighOneCell(aCell, fromHL, toHL);
  197.             }
  198.             break;
  199.     }
  200. }
  201.  
  202. pascal GridViewPart TGroupListView::IdentifyPoint(const VPoint& thePoint,
  203.                                              GridCell& aCell)
  204. {
  205.     GridViewPart part = inherited::IdentifyPoint(thePoint, aCell);
  206.     if (part == badChoice)
  207.         return part;
  208.     CRect r;
  209.     GetCellTextRect(aCell, r);
  210.     CPoint pt = ViewToQDPt(thePoint);
  211.     if (!r.Contains(pt))
  212.         return badChoice;
  213.     return part;    
  214. }
  215. //========================================================================
  216. void TGroupListView::UpdateList()
  217. {
  218.     if (fNumOfRows)
  219.         DelRowFirst(fNumOfRows);
  220.     InsRowFirst(short(fGroupList->GetSize()), fGridViewTextStyle.fRowHeight);
  221. }
  222.  
  223. void TGroupListView::UpdateGroupStatus(const CStr255 &dotName, Boolean hasNewArticles)
  224. {
  225.     ArrayIndex listIndex = fGroupList->FindIndexFromName(dotName);
  226.     if (listIndex == kEmptyIndex)
  227.         return;
  228.     NewArticleStat newStat = (hasNewArticles ? kHasNew : kNoNew);
  229.     NewArticleStat oldStat = fGroupList->GetNewArticleStat(listIndex);
  230.     if (newStat == oldStat)
  231.         return;
  232.     fGroupList->SetNewArticleStat(listIndex, newStat);
  233.     Focus();
  234.     VRect vr;
  235.     CellToVRect(GridCell(1, short(listIndex)), vr);
  236.     vr.left = fGridViewTextStyle.fHorzOffset;
  237.     vr.right = vr.left + 2 * fGridViewTextStyle.fHorzOffset - 2;
  238.     InvalidateVRect(vr);
  239. }
  240.  
  241. //========================================================================
  242. TGroupList *TGroupListView::GetSelectionAsList()
  243. {
  244.     TGroupList *groupList = nil;
  245.     VOLATILE(groupList);
  246.     FailInfo fi;
  247.     if (fi.Try())
  248.     {
  249.         TGroupList *gl = new TGroupList();
  250.         gl->IGroupList(nil);
  251.         groupList = gl;
  252.         CSelectedCellIterator iter(this);
  253.         for (GridCell aCell = iter.FirstCell(); iter.More(); aCell = iter.NextCell())
  254.         {
  255.             CStr255 name;
  256.             fGroupList->GetGroupAt(aCell.v, name);
  257.             groupList->InsertGroupBefore(groupList->fSize + 1, name);
  258.         }
  259.         fi.Success();
  260.         return groupList;
  261.     }
  262.     else // fail
  263.     {
  264.         FreeIfObject(groupList); groupList = nil;
  265.         fi.ReSignal();
  266.     }
  267. }
  268.  
  269. void TGroupListView::AddGroupsFromListBefore(ArrayIndex index, TGroupList *groupList)
  270. {
  271.     SetEmptySelection(kHighlight);
  272.     short noGroups = short(fGroupList->AddGroupsFromListBefore(index, groupList));
  273.     InsRowBefore(short(index), noGroups, fGridViewTextStyle.fRowHeight);
  274.     if (fNumOfRows && noGroups > 0 && noGroups < fGroupList->GetSize())
  275.     {
  276.         CRect r(1, short(index), 1, short(index) + noGroups - 1);
  277.         SetSelectionRect(r, false, true, true);
  278.     }
  279. }
  280.  
  281. void TGroupListView::OpenSelection(Boolean updateDatabase)
  282. {
  283.     FailSpaceIsLow();
  284.     short numSelected = 0;
  285.     CSelectedCellIterator iter(this);
  286.     for (GridCell aCell = iter.FirstCell(); iter.More(); aCell = iter.NextCell())
  287.         numSelected++;
  288.     if (numSelected > kOpenManyGroupsLimit)
  289.     {
  290.         CStr255 num;
  291.         NumToString(numSelected, num);
  292.         ParamText(gEmptyString, gEmptyString, gEmptyString, num);
  293.         if (MacAppAlert(phOpenManyGroups, nil) != ok)
  294.             Failure(0, 0);
  295.     }
  296.     for (aCell = iter.FirstCell(); iter.More(); aCell = iter.NextCell())
  297.     {
  298.         CStr255 name;
  299.         fGroupList->GetGroupAt(aCell.v, name);
  300.         TOpenGroupCommand *aCommand = new TOpenGroupCommand();
  301.         aCommand->IOpenGroupCommand(name, updateDatabase, false, true);
  302.         gApplWideThreads->ExecuteCommand(aCommand, "TOpenGroupCommand (TGroupListView)");
  303.     }
  304. }
  305.  
  306. void TGroupListView::DeleteGroup(short line)
  307. {
  308.     fGroupList->DeleteGroupAt(line);
  309.     DelRowAt(line, 1);
  310. }
  311.  
  312. void TGroupListView::DeleteSelection()
  313. {
  314.     CSelectedCellIterator iter(this, false, true, true);
  315.     for (GridCell aCell = iter.FirstCell(); iter.More(); aCell = iter.NextCell())
  316.     {
  317.         SelectCell(aCell, true, false, false);
  318.         DeleteGroup(aCell.v);
  319.     }
  320. }
  321.  
  322. void TGroupListView::DeleteGroupsFromList(TGroupList *groupList)
  323. {
  324.     CArrayIterator iter(groupList);
  325.     for (ArrayIndex delIndex = iter.FirstIndex(); iter.More(); delIndex = iter.NextIndex())
  326.     {
  327.         CStr255 name;
  328.         groupList->GetGroupAt(delIndex, name);
  329.         ArrayIndex index = fGroupList->FindIndexFromName(name);
  330.         if (index != kEmptyIndex)
  331.             DeleteGroup(short(index));
  332.     }
  333. }
  334.  
  335. TGroupList *TGroupListView::GetGroupList()
  336. {
  337.     return fGroupList;
  338. }
  339.  
  340. pascal void TGroupListView::DoKeyEvent(TToolboxEvent *event)
  341. {
  342.     if (!this->IsEnabled())
  343.     {
  344.         inherited::DoKeyEvent(event);
  345.         return;
  346.     }
  347.     switch (event->fCharacter)
  348.     {
  349.         case chSpace:
  350.             {
  351.                 if (!fNumOfRows)
  352.                     break;
  353.                 OpenSelection(!event->IsOptionKeyPressed());
  354.                 GridCell aCell;
  355.                 if (IsAnyCellSelected())
  356.                     aCell = FirstSelectedCell();
  357.                 else
  358.                     aCell = GridCell(1, 0);
  359.                 while (++aCell.v <= fNumOfRows)
  360.                 {
  361.                     if (fGroupList->GetNewArticleStat(aCell.v) != kNoNew)
  362.                         break;
  363.                 }
  364.                 if (aCell.v <= fNumOfRows)
  365.                     SelectCell(aCell, false, true, true);
  366.                 else
  367.                     SetEmptySelection(kHighlight);
  368.                 ScrollSelectionIntoView(kRedraw);
  369.             }
  370.             break;
  371.  
  372.         case chUp:
  373.             {
  374.                 GridCell aCell;
  375.                 if (IsAnyCellSelected())
  376.                 {
  377.                     aCell = FirstSelectedCell();
  378.                     aCell.v--;
  379.                 }
  380.                 else
  381.                     aCell = GridCell(1, fNumOfRows);
  382.                 if (aCell.v >= 1)
  383.                 {
  384.                     SelectCell(aCell, false, true, true);
  385.                     ScrollSelectionIntoView(kRedraw);
  386.                     Focus();
  387.                     Update();
  388.                 }
  389.             }
  390.             break;
  391.  
  392.         case chDown:
  393.             {
  394.                 GridCell aCell;
  395.                 if (IsAnyCellSelected())
  396.                 {
  397.                     aCell = LastSelectedCell();
  398.                     aCell.v++;
  399.                 }
  400.                 else
  401.                     aCell = GridCell(1, 1);
  402.                 if (aCell.v <= fNumOfRows)
  403.                 {
  404.                     SelectCell(aCell, false, true, true);
  405.                     ScrollSelectionIntoView(kRedraw);
  406.                     Focus();
  407.                     Update();
  408.                 }
  409.             }
  410.             break;
  411.  
  412.         case chEnter:
  413.         case chReturn:
  414.             OpenSelection(!event->IsOptionKeyPressed());
  415.             break;
  416.             
  417.         case chBackspace:
  418.             {
  419.                 GridCell cell = FirstSelectedCell();
  420.                 DeleteSelection();
  421.                 if (event->IsOptionKeyPressed() && cell.v > 0 && cell.v <= fNumOfRows)
  422.                     SelectCell(cell, false, true, true);
  423.                 ScrollSelectionIntoView(kRedraw);
  424.             }
  425.             break;
  426.     
  427.         case chTab:
  428.             {
  429.                 TListTabKeyCommand *cmd = new TListTabKeyCommand();
  430.                 cmd->IListTabKeyCommand(this, !event->IsShiftKeyPressed());
  431.                 PostCommand(cmd);
  432.             }
  433.             break;
  434.             
  435.         default:
  436.             if (event->fCharacter >= 32)
  437.             {
  438.                 TListTypeName *cmd = new TListTypeName();
  439.                 cmd->IListTypeName(this, event);
  440.                 PostCommand(cmd);
  441.             }
  442.             else
  443.                 inherited::DoKeyEvent(event);            
  444.     } // case
  445. }
  446.  
  447. pascal void TGroupListView::DoMouseCommand(VPoint &theMouse,
  448.                                  TToolboxEvent *event,
  449.                                  CPoint /* hysteresis */)
  450. {
  451.     GridCell aCell;
  452.     if (IdentifyPoint(theMouse, aCell) == badChoice)
  453.     {
  454.         if (!event->IsShiftKeyPressed())
  455.             SetEmptySelection(kHighlight);
  456.         return;
  457.     }
  458.     if (event->fClickCount > 1) 
  459.     {
  460.         OpenSelection(!event->IsOptionKeyPressed());
  461.         return;
  462.     }
  463.     Focus();
  464.     if (event->IsShiftKeyPressed())
  465.         SelectCell(aCell, true, true, !IsCellSelected(aCell));
  466.     else if (!IsCellSelected(aCell))
  467.         SelectCell(aCell, false, true, true);
  468.  
  469.     TUnsubscribeGroupTracker *tracker = new TUnsubscribeGroupTracker();
  470.     tracker->IUnsubscribeGroupTracker(this, theMouse, event->IsOptionKeyPressed());
  471.     PostCommand(tracker);
  472. }
  473.  
  474.  
  475. pascal void TGroupListView::DoMenuCommand(CommandNumber aCommandNumber)
  476. {
  477.     switch (aCommandNumber)
  478.     {
  479.         case cClear:
  480.             DeleteSelection();
  481.             break;
  482.  
  483.         case cCheckForNewArticles:
  484.             fDoc->CheckForNewArticlesNow();
  485.             break;
  486.             
  487.         default:
  488.             {
  489.                 StandardGridViewTextStyle gvts = fGridViewTextStyle;
  490.                 if (gNewsAppl->HandleFontMenu(aCommandNumber, gvts.fTextStyle))
  491.                 {
  492.                     CalcStandardGridViewFont(gvts);
  493.                     fGridViewTextStyle = gvts;
  494.                     gPrefs->SetTextStylePrefs('TSgl', gvts.fTextStyle);
  495.                     ChangedFont();
  496.                 }
  497.                 else
  498.                     inherited::DoMenuCommand(aCommandNumber);
  499.             }
  500.     }
  501. }
  502.  
  503. pascal void TGroupListView::DoSetupMenus()
  504. {
  505.     gNewsAppl->EnableFontMenu(fGridViewTextStyle.fTextStyle);
  506.     Enable(cSelectAll, true);
  507.     Enable(cClear, IsAnyCellSelected());
  508.     Enable(cCheckForNewArticles, fNumOfRows && !fDoc->IsCheckingForNewArticlesNow());
  509.     inherited::DoSetupMenus();
  510. }
  511.