MythTV  0.26-pre
TokenGroup.cpp
Go to the documentation of this file.
00001 /* TokenGroup.cpp
00002 
00003    Copyright (C)  David C. J. Matthews 2004  dm at prolingua.co.uk
00004 
00005    This program is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU General Public License
00007    as published by the Free Software Foundation; either version 2
00008    of the License, or (at your option) any later version.
00009 
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013    GNU General Public License for more details.
00014 
00015    You should have received a copy of the GNU General Public License
00016    along with this program; if not, write to the Free Software
00017    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00018    Or, point your browser to http://www.gnu.org/copyleft/gpl.html
00019 
00020 */
00021 
00022 
00023 #include "TokenGroup.h"
00024 #include "Presentable.h"
00025 #include "Ingredients.h"
00026 #include "Root.h"
00027 #include "BaseClasses.h"
00028 #include "ParseNode.h"
00029 #include "ASN1Codes.h"
00030 #include "Engine.h"
00031 
00032 void MHTokenGroupItem::Initialise(MHParseNode *p, MHEngine *engine)
00033 {
00034     // A pair consisting of an object reference and an optional action slot sequence.
00035     m_Object.Initialise(p->GetSeqN(0), engine);
00036 
00037     if (p->GetSeqCount() > 1)
00038     {
00039         MHParseNode *pSlots = p->GetSeqN(1);
00040 
00041         for (int i = 0; i < pSlots->GetSeqCount(); i++)
00042         {
00043             MHParseNode *pAct = pSlots->GetSeqN(i);
00044             MHActionSequence *pActions = new MHActionSequence;
00045             m_ActionSlots.Append(pActions);
00046 
00047             // The action slot entry may be NULL.
00048             if (pAct->m_nNodeType != MHParseNode::PNNull)
00049             {
00050                 pActions->Initialise(pAct, engine);
00051             }
00052         }
00053     }
00054 }
00055 
00056 void MHTokenGroupItem::PrintMe(FILE *fd, int nTabs) const
00057 {
00058     PrintTabs(fd, nTabs);
00059     fprintf(fd, "( ");
00060     m_Object.PrintMe(fd, nTabs + 1);
00061     fprintf(fd, "\n");
00062 
00063     if (m_ActionSlots.Size() != 0)
00064     {
00065         PrintTabs(fd, nTabs + 1);
00066         fprintf(fd, ":ActionSlots (\n");
00067 
00068         for (int i = 0; i < m_ActionSlots.Size(); i++)
00069         {
00070             PrintTabs(fd, nTabs + 2);
00071             fprintf(fd, "(\n");
00072             MHActionSequence *pActions = m_ActionSlots.GetAt(i);
00073 
00074             if (pActions->Size() == 0)
00075             {
00076                 PrintTabs(fd, nTabs + 2);
00077                 fprintf(fd, "NULL\n");
00078             }
00079             else
00080             {
00081                 pActions->PrintMe(fd, nTabs + 2);
00082             }
00083 
00084             PrintTabs(fd, nTabs + 2);
00085             fprintf(fd, ")\n");
00086         }
00087 
00088         PrintTabs(fd, nTabs + 1);
00089         fprintf(fd, ")\n");
00090     }
00091 
00092     PrintTabs(fd, nTabs);
00093     fprintf(fd, ")\n");
00094 }
00095 
00096 void MHMovement::Initialise(MHParseNode *p, MHEngine * /*engine*/)
00097 {
00098     for (int i = 0; i < p->GetSeqCount(); i++)
00099     {
00100         m_Movement.Append(p->GetSeqN(i)->GetIntValue());
00101     }
00102 }
00103 
00104 void MHMovement::PrintMe(FILE *fd, int nTabs) const
00105 {
00106     PrintTabs(fd, nTabs);
00107     fprintf(fd, "( ");
00108 
00109     for (int i = 0; i < m_Movement.Size(); i++)
00110     {
00111         fprintf(fd, "%d ", m_Movement.GetAt(i));
00112     }
00113 
00114     fprintf(fd, ")\n");
00115 }
00116 
00117 MHTokenGroup::MHTokenGroup()
00118 {
00119     m_nTokenPosition = 1; // Initial value
00120 }
00121 
00122 void MHTokenGroup::Initialise(MHParseNode *p, MHEngine *engine)
00123 {
00124     MHPresentable::Initialise(p, engine);
00125     MHParseNode *pMovements = p->GetNamedArg(C_MOVEMENT_TABLE);
00126 
00127     if (pMovements)
00128     {
00129         for (int i = 0; i < pMovements->GetArgCount(); i++)
00130         {
00131             MHMovement *pMove = new MHMovement;
00132             m_MovementTable.Append(pMove);
00133             pMove->Initialise(pMovements->GetArgN(i), engine);
00134         }
00135     }
00136 
00137     MHParseNode *pTokenGrp = p->GetNamedArg(C_TOKEN_GROUP_ITEMS);
00138 
00139     if (pTokenGrp)
00140     {
00141         for (int i = 0; i < pTokenGrp->GetArgCount(); i++)
00142         {
00143             MHTokenGroupItem *pToken = new MHTokenGroupItem;
00144             m_TokenGrpItems.Append(pToken);
00145             pToken->Initialise(pTokenGrp->GetArgN(i), engine);
00146         }
00147     }
00148 
00149     MHParseNode *pNoToken = p->GetNamedArg(C_NO_TOKEN_ACTION_SLOTS);
00150 
00151     if (pNoToken)
00152     {
00153         for (int i = 0; i < pNoToken->GetArgCount(); i++)
00154         {
00155             MHParseNode *pAct = pNoToken->GetArgN(i);
00156             MHActionSequence *pActions = new MHActionSequence;
00157             m_NoTokenActionSlots.Append(pActions);
00158 
00159             // The action slot entry may be NULL.
00160             if (pAct->m_nNodeType != MHParseNode::PNNull)
00161             {
00162                 pActions->Initialise(pAct, engine);
00163             }
00164         }
00165     }
00166 }
00167 
00168 // This is used to print the contents of the token group.
00169 void MHTokenGroup::PrintContents(FILE *fd, int nTabs) const
00170 {
00171     MHPresentable::PrintMe(fd, nTabs + 1);
00172 
00173     if (m_MovementTable.Size() != 0)
00174     {
00175         PrintTabs(fd, nTabs + 1);
00176         fprintf(fd, ":MovementTable (\n");
00177 
00178         for (int i = 0; i < m_MovementTable.Size(); i++)
00179         {
00180             m_MovementTable.GetAt(i)->PrintMe(fd, nTabs + 2);
00181         }
00182 
00183         PrintTabs(fd, nTabs + 1);
00184         fprintf(fd, ")\n");
00185     }
00186 
00187     if (m_TokenGrpItems.Size() != 0)
00188     {
00189         PrintTabs(fd, nTabs + 1);
00190         fprintf(fd, ":TokenGroupItems (\n");
00191 
00192         for (int i = 0; i < m_TokenGrpItems.Size(); i++)
00193         {
00194             m_TokenGrpItems.GetAt(i)->PrintMe(fd, nTabs + 2);
00195         }
00196 
00197         PrintTabs(fd, nTabs + 1);
00198         fprintf(fd, ")\n");
00199     }
00200 
00201     if (m_NoTokenActionSlots.Size() != 0)
00202     {
00203         PrintTabs(fd, nTabs + 1);
00204         fprintf(fd, ":NoTokenActionSlots (\n");
00205 
00206         for (int i = 0; i < m_NoTokenActionSlots.Size(); i++)
00207         {
00208             MHActionSequence *pActions = m_NoTokenActionSlots.GetAt(i);
00209 
00210             if (pActions->Size() == 0)
00211             {
00212                 PrintTabs(fd, nTabs + 2);
00213                 fprintf(fd, "NULL ");
00214             }
00215             else
00216             {
00217                 pActions->PrintMe(fd, nTabs + 2);
00218             }
00219         }
00220 
00221         PrintTabs(fd, nTabs + 1);
00222         fprintf(fd, ")\n");
00223     }
00224 
00225 }
00226 
00227 void MHTokenGroup::PrintMe(FILE *fd, int nTabs) const
00228 {
00229     PrintTabs(fd, nTabs);
00230     fprintf(fd, "{:TokenGroup ");
00231     PrintContents(fd, nTabs);
00232     PrintTabs(fd, nTabs);
00233     fprintf(fd, "}\n");
00234 }
00235 
00236 // Activate the token group following the standard.
00237 void MHTokenGroup::Activation(MHEngine *engine)
00238 {
00239     if (m_fRunning)
00240     {
00241         return;
00242     }
00243 
00244     MHPresentable::Activation(engine);
00245 
00246     // We're supposed to apply Activation to each of the "items" but it isn't clear
00247     // exactly what that means.  Assume it means each of the visibles.
00248     for (int i = 0; i < m_TokenGrpItems.Size(); i++)
00249     {
00250         MHObjectRef *pObject = &m_TokenGrpItems.GetAt(i)->m_Object;
00251 
00252         // The object reference may be the null reference.
00253         // Worse: it seems that sometimes in BBC's MHEG the reference simply doesn't exist.
00254         if (pObject->IsSet())
00255         {
00256             try
00257             {
00258                 engine->FindObject(m_TokenGrpItems.GetAt(i)->m_Object)->Activation(engine);
00259             }
00260             catch (char const *) {}
00261         }
00262     }
00263 
00264     engine->EventTriggered(this, EventTokenMovedTo, m_nTokenPosition);
00265     m_fRunning = true;
00266     engine->EventTriggered(this, EventIsRunning);
00267 }
00268 
00269 void MHTokenGroup::Deactivation(MHEngine *engine)
00270 {
00271     if (! m_fRunning)
00272     {
00273         return;
00274     }
00275 
00276     engine->EventTriggered(this, EventTokenMovedFrom, m_nTokenPosition);
00277     MHPresentable::Deactivation(engine);
00278 }
00279 
00280 // Internal function to generate the appropriate events.
00281 void MHTokenGroup::TransferToken(int newPos, MHEngine *engine)
00282 {
00283     if (newPos != m_nTokenPosition)
00284     {
00285         engine->EventTriggered(this, EventTokenMovedFrom, m_nTokenPosition);
00286         m_nTokenPosition = newPos;
00287         engine->EventTriggered(this, EventTokenMovedTo, m_nTokenPosition);
00288     }
00289 }
00290 
00291 // Perform the actions depending on where the token is.
00292 void MHTokenGroup::CallActionSlot(int n, MHEngine *engine)
00293 {
00294     if (m_nTokenPosition == 0)   // No slot has the token.
00295     {
00296         if (n > 0 && n <= m_NoTokenActionSlots.Size())
00297         {
00298             engine->AddActions(*(m_NoTokenActionSlots.GetAt(n - 1)));
00299         }
00300     }
00301     else
00302     {
00303         if (m_nTokenPosition > 0 && m_nTokenPosition <= m_TokenGrpItems.Size())
00304         {
00305             MHTokenGroupItem *pGroup = m_TokenGrpItems.GetAt(m_nTokenPosition - 1);
00306 
00307             if (n > 0 && n <= pGroup->m_ActionSlots.Size())
00308             {
00309                 engine->AddActions(*(pGroup->m_ActionSlots.GetAt(n - 1)));
00310             }
00311         }
00312     }
00313 }
00314 
00315 void MHTokenGroup::Move(int n, MHEngine *engine)
00316 {
00317     if (m_nTokenPosition == 0 || n < 1 || n > m_MovementTable.Size())
00318     {
00319         TransferToken(0, engine);    // Not in the standard
00320     }
00321     else
00322     {
00323         TransferToken(m_MovementTable.GetAt(n - 1)->m_Movement.GetAt(m_nTokenPosition - 1), engine);
00324     }
00325 }
00326 
00327 // ListGroup.  This is a complex class and the description was extensively revised in the MHEG corrigendum.
00328 // It doesn't seem to be used a great deal in practice and quite a few of the actions haven't been tested.
00329 
00330 MHListGroup::MHListGroup()
00331 {
00332     m_fWrapAround = false;
00333     m_fMultipleSelection = false;
00334     m_nFirstItem = 1;
00335     m_nLastFirstItem = m_nFirstItem;
00336     m_nLastCount = 0;
00337 }
00338 MHListGroup::~MHListGroup()
00339 {
00340     while (!m_ItemList.isEmpty())
00341     {
00342         delete m_ItemList.takeFirst();
00343     }
00344 }
00345 
00346 void MHListGroup::Initialise(MHParseNode *p, MHEngine *engine)
00347 {
00348     MHTokenGroup::Initialise(p, engine);
00349     MHParseNode *pPositions = p->GetNamedArg(C_POSITIONS);
00350 
00351     if (pPositions)
00352     {
00353         for (int i = 0; i < pPositions->GetArgCount(); i++)
00354         {
00355             MHParseNode *pPos = pPositions->GetArgN(i);
00356             QPoint pos(pPos->GetSeqN(0)->GetIntValue(), pPos->GetSeqN(1)->GetIntValue());
00357             m_Positions.Append(pos);
00358         }
00359     }
00360 
00361     MHParseNode *pWrap = p->GetNamedArg(C_WRAP_AROUND);
00362 
00363     if (pWrap)
00364     {
00365         m_fWrapAround = pWrap->GetArgN(0)->GetBoolValue();
00366     }
00367 
00368     MHParseNode *pMultiple = p->GetNamedArg(C_WRAP_AROUND);
00369 
00370     if (pMultiple)
00371     {
00372         m_fMultipleSelection = pMultiple->GetArgN(0)->GetBoolValue();
00373     }
00374 }
00375 
00376 void MHListGroup::PrintMe(FILE *fd, int nTabs) const
00377 {
00378     PrintTabs(fd, nTabs);
00379     fprintf(fd, "{:ListGroup ");
00380     MHTokenGroup::PrintContents(fd, nTabs);
00381     PrintTabs(fd, nTabs + 1);
00382     fprintf(fd, ":Positions (");
00383 
00384     for (int i = 0; i < m_Positions.Size(); i++)
00385     {
00386         fprintf(fd, " ( %d %d )", m_Positions.GetAt(i).x(), m_Positions.GetAt(i).y());
00387     }
00388 
00389     fprintf(fd, ")\n");
00390 
00391     if (m_fWrapAround)
00392     {
00393         PrintTabs(fd, nTabs + 1);
00394         fprintf(fd, ":WrapAround true\n");
00395     }
00396 
00397     if (m_fMultipleSelection)
00398     {
00399         PrintTabs(fd, nTabs + 1);
00400         fprintf(fd, ":MultipleSelection true\n");
00401     }
00402 
00403     PrintTabs(fd, nTabs);
00404     fprintf(fd, "}\n");
00405 }
00406 
00407 void MHListGroup::Preparation(MHEngine *engine)
00408 {
00409     MHTokenGroup::Preparation(engine);
00410 
00411     for (int i = 0; i < m_TokenGrpItems.Size(); i++)
00412     {
00413         // Find the item and add it to the list if it isn't already there.
00414         try
00415         {
00416             MHRoot *pItem = (MHRoot *)engine->FindObject(m_TokenGrpItems.GetAt(i)->m_Object);
00417             MHListItem *p = 0;
00418             QList<MHListItem *>::iterator it = m_ItemList.begin();
00419 
00420             for (; it != m_ItemList.end(); ++it)
00421             {
00422                 p = *it;
00423 
00424                 if (p->m_pVisible == pItem)
00425                 {
00426                     break;
00427                 }
00428             }
00429 
00430             if (!p)
00431             {
00432                 m_ItemList.append(new MHListItem(pItem));
00433             }
00434         }
00435         catch (...)  // Ignore invalid or null objects.
00436         {
00437         }
00438     }
00439 }
00440 
00441 void MHListGroup::Destruction(MHEngine *engine)
00442 {
00443     // Reset the positions of the visibles.
00444     for (int j = 0; j < m_ItemList.size(); j++)
00445     {
00446         m_ItemList.at(j)->m_pVisible->ResetPosition();
00447     }
00448 
00449     MHTokenGroup::Destruction(engine);
00450 }
00451 
00452 void MHListGroup::Activation(MHEngine *engine)
00453 {
00454     m_fFirstItemDisplayed = m_fLastItemDisplayed = false;
00455     MHTokenGroup::Activation(engine);
00456     Update(engine);
00457 }
00458 
00459 
00460 void MHListGroup::Deactivation(MHEngine *engine)
00461 {
00462     // Deactivate the visibles.
00463     for (int j = 0; j < m_ItemList.size(); j++)
00464     {
00465         m_ItemList.at(j)->m_pVisible->Deactivation(engine);
00466     }
00467 
00468     MHTokenGroup::Deactivation(engine);
00469 }
00470 
00471 // Update action - set the position of the cells to be displayed and deactivate those
00472 // which aren't.
00473 void MHListGroup::Update(MHEngine *engine)
00474 {
00475     if (!m_ItemList.size())   // Special cases when the list becomes empty
00476     {
00477         if (m_fFirstItemDisplayed)
00478         {
00479             m_fFirstItemDisplayed = false;
00480             engine->EventTriggered(this, EventFirstItemPresented, false);
00481         }
00482 
00483         if (m_fLastItemDisplayed)
00484         {
00485             m_fLastItemDisplayed = false;
00486             engine->EventTriggered(this, EventLastItemPresented, false);
00487         }
00488     }
00489     else   // Usual case.
00490     {
00491         for (int i = 0; i < m_ItemList.size(); i++)
00492         {
00493             MHRoot *pVis = m_ItemList.at(i)->m_pVisible;
00494             int nCell = i + 1 - m_nFirstItem; // Which cell does this item map onto?
00495 
00496             if (nCell >= 0 && nCell < m_Positions.Size())
00497             {
00498                 if (i == 0 && ! m_fFirstItemDisplayed)
00499                 {
00500                     m_fFirstItemDisplayed = true;
00501                     engine->EventTriggered(this, EventFirstItemPresented, true);
00502                 }
00503 
00504                 if (i == m_ItemList.size() - 1 && ! m_fLastItemDisplayed)
00505                 {
00506                     m_fLastItemDisplayed = true;
00507                     engine->EventTriggered(this, EventLastItemPresented, true);
00508                 }
00509 
00510                 try
00511                 {
00512                     pVis->SetPosition(m_Positions.GetAt(i - m_nFirstItem + 1).x(), m_Positions.GetAt(i - m_nFirstItem + 1).y(), engine);
00513                 }
00514                 catch (...) {}
00515 
00516                 if (! pVis->GetRunningStatus())
00517                 {
00518                     pVis->Activation(engine);
00519                 }
00520             }
00521             else
00522             {
00523                 if (i == 0 && m_fFirstItemDisplayed)
00524                 {
00525                     m_fFirstItemDisplayed = false;
00526                     engine->EventTriggered(this, EventFirstItemPresented, false);
00527                 }
00528 
00529                 if (i == m_ItemList.size() - 1 && m_fLastItemDisplayed)
00530                 {
00531                     m_fLastItemDisplayed = false;
00532                     engine->EventTriggered(this, EventLastItemPresented, false);
00533                 }
00534 
00535                 if (pVis->GetRunningStatus())
00536                 {
00537                     pVis->Deactivation(engine);
00538                     pVis->ResetPosition();
00539                 }
00540             }
00541         }
00542     }
00543 
00544     // Generate the HeadItems and TailItems events.  Even in the MHEG corrigendum this is unclear.
00545     // I'm not at all sure this is right.
00546     if (m_nLastFirstItem != m_nFirstItem)
00547     {
00548         engine->EventTriggered(this, EventHeadItems, m_nFirstItem);
00549     }
00550 
00551     if (m_nLastCount - m_nLastFirstItem != m_ItemList.size() - m_nFirstItem)
00552     {
00553         engine->EventTriggered(this, EventTailItems, m_ItemList.size() - m_nFirstItem);
00554     }
00555 
00556     m_nLastCount = m_ItemList.size();
00557     m_nLastFirstItem = m_nFirstItem;
00558 }
00559 
00560 // Add an item to the list
00561 void MHListGroup::AddItem(int nIndex, MHRoot *pItem, MHEngine *engine)
00562 {
00563     // See if the item is already there and ignore this if it is.
00564     QList<MHListItem *>::iterator it = m_ItemList.begin();
00565 
00566     for (; it != m_ItemList.end(); ++it)
00567     {
00568         if ((*it)->m_pVisible == pItem)
00569         {
00570             return;
00571         }
00572     }
00573 
00574     // Ignore this if the index is out of range
00575     if (nIndex < 1 || nIndex > m_ItemList.size() + 1)
00576     {
00577         return;
00578     }
00579 
00580     // Insert it at the appropriate position (MHEG indexes count from 1).
00581     m_ItemList.insert(nIndex - 1, new MHListItem(pItem));
00582 
00583     if (nIndex <= m_nFirstItem && m_nFirstItem < m_ItemList.size())
00584     {
00585         m_nFirstItem++;
00586     }
00587 
00588     Update(engine); // Apply the update behaviour
00589 }
00590 
00591 // Remove an item from the list
00592 void MHListGroup::DelItem(MHRoot *pItem, MHEngine *)
00593 {
00594     // See if the item is already there and ignore this if it is.
00595     for (int i = 0; i < m_ItemList.size(); i++)
00596     {
00597         if (m_ItemList.at(i)->m_pVisible == pItem)   // Found it - remove it from the list and reset the posn.
00598         {
00599             delete m_ItemList.takeAt(i);
00600             pItem->ResetPosition();
00601 
00602             if (i + 1 < m_nFirstItem && m_nFirstItem > 1)
00603             {
00604                 m_nFirstItem--;
00605             }
00606 
00607             return;
00608         }
00609     }
00610 }
00611 
00612 // Set the selection status of the item to true
00613 void MHListGroup::Select(int nIndex, MHEngine *engine)
00614 {
00615     MHListItem *pListItem = m_ItemList.at(nIndex - 1);
00616 
00617     if (pListItem == 0 || pListItem->m_fSelected)
00618     {
00619         return;    // Ignore if already selected.
00620     }
00621 
00622     if (! m_fMultipleSelection)
00623     {
00624         // Deselect any existing selections.
00625         for (int i = 0; i < m_ItemList.size(); i++)
00626             if (m_ItemList.at(i)->m_fSelected)
00627             {
00628                 Deselect(i + 1, engine);
00629             }
00630     }
00631 
00632     pListItem->m_fSelected = true;
00633     engine->EventTriggered(this, EventItemSelected, nIndex);
00634 }
00635 
00636 // Set the selection status of the item to false
00637 void MHListGroup::Deselect(int nIndex, MHEngine *engine)
00638 {
00639     MHListItem *pListItem = m_ItemList.at(nIndex - 1);
00640 
00641     if (pListItem == 0 || ! pListItem->m_fSelected)
00642     {
00643         return;    // Ignore if not selected.
00644     }
00645 
00646     pListItem->m_fSelected = false;
00647     engine->EventTriggered(this, EventItemDeselected, nIndex);
00648 }
00649 
00650 // Return the reference to the visible at the particular position.
00651 void MHListGroup::GetCellItem(int nCell, const MHObjectRef &itemDest, MHEngine *engine)
00652 {
00653     if (nCell < 1)
00654     {
00655         nCell = 1;    // First cell
00656     }
00657 
00658     if (nCell > m_Positions.Size())
00659     {
00660         nCell = m_Positions.Size();    // Last cell.
00661     }
00662 
00663     int nVisIndex = nCell + m_nFirstItem - 2;
00664 
00665     if (nVisIndex >= 0 && nVisIndex < m_ItemList.size())
00666     {
00667         MHRoot *pVis = m_ItemList.at(nVisIndex)->m_pVisible;
00668         engine->FindObject(itemDest)->SetVariableValue(pVis->m_ObjectReference);
00669     }
00670     else
00671     {
00672         engine->FindObject(itemDest)->SetVariableValue(MHObjectRef::Null);
00673     }
00674 }
00675 
00676 int MHListGroup::AdjustIndex(int nIndex) // Added in the MHEG corrigendum
00677 {
00678     int nItems = m_ItemList.size();
00679 
00680     if (nItems == 0)
00681     {
00682         return 1;
00683     }
00684 
00685     if (nIndex > nItems)
00686     {
00687         return ((nIndex - 1) % nItems) + 1;
00688     }
00689     else if (nIndex < 0)
00690     {
00691         return nItems - ((-nIndex) % nItems);
00692     }
00693     else
00694     {
00695         return nIndex;
00696     }
00697 }
00698 
00699 void MHListGroup::GetListItem(int nCell, const MHObjectRef &itemDest, MHEngine *engine)
00700 {
00701     if (m_fWrapAround)
00702     {
00703         nCell = AdjustIndex(nCell);
00704     }
00705 
00706     if (nCell < 1 || nCell > m_ItemList.size())
00707     {
00708         return;    // Ignore it if it's out of range and not wrapping
00709     }
00710 
00711     engine->FindObject(itemDest)->SetVariableValue(m_ItemList.at(nCell - 1)->m_pVisible->m_ObjectReference);
00712 }
00713 
00714 void MHListGroup::GetItemStatus(int nCell, const MHObjectRef &itemDest, MHEngine *engine)
00715 {
00716     if (m_fWrapAround)
00717     {
00718         nCell = AdjustIndex(nCell);
00719     }
00720 
00721     if (nCell < 1 || nCell > m_ItemList.size())
00722     {
00723         return;
00724     }
00725 
00726     engine->FindObject(itemDest)->SetVariableValue(m_ItemList.at(nCell - 1)->m_fSelected);
00727 }
00728 
00729 void MHListGroup::SelectItem(int nCell, MHEngine *engine)
00730 {
00731     if (m_fWrapAround)
00732     {
00733         nCell = AdjustIndex(nCell);
00734     }
00735 
00736     if (nCell < 1 || nCell > m_ItemList.size())
00737     {
00738         return;
00739     }
00740 
00741     Select(nCell, engine);
00742 }
00743 
00744 void MHListGroup::DeselectItem(int nCell, MHEngine *engine)
00745 {
00746     if (m_fWrapAround)
00747     {
00748         nCell = AdjustIndex(nCell);
00749     }
00750 
00751     if (nCell < 1 || nCell > m_ItemList.size())
00752     {
00753         return;
00754     }
00755 
00756     Deselect(nCell, engine);
00757 }
00758 
00759 void MHListGroup::ToggleItem(int nCell, MHEngine *engine)
00760 {
00761     if (m_fWrapAround)
00762     {
00763         nCell = AdjustIndex(nCell);
00764     }
00765 
00766     if (nCell < 1 || nCell > m_ItemList.size())
00767     {
00768         return;
00769     }
00770 
00771     if (m_ItemList.at(nCell - 1)->m_fSelected)
00772     {
00773         Deselect(nCell, engine);
00774     }
00775     else
00776     {
00777         Select(nCell, engine);
00778     }
00779 }
00780 
00781 void MHListGroup::ScrollItems(int nCell, MHEngine *engine)
00782 {
00783     nCell += m_nFirstItem;
00784 
00785     if (m_fWrapAround)
00786     {
00787         nCell = AdjustIndex(nCell);
00788     }
00789 
00790     if (nCell < 1 || nCell > m_ItemList.size())
00791     {
00792         return;
00793     }
00794 
00795     m_nFirstItem = nCell;
00796     Update(engine);
00797 }
00798 
00799 void MHListGroup::SetFirstItem(int nCell, MHEngine *engine)
00800 {
00801     if (m_fWrapAround)
00802     {
00803         nCell = AdjustIndex(nCell);
00804     }
00805 
00806     if (nCell < 1 || nCell > m_ItemList.size())
00807     {
00808         return;
00809     }
00810 
00811     m_nFirstItem = nCell;
00812     Update(engine);
00813 }
00814 
00815 
00816 
00817 // Actions
00818 void MHAddItem::Initialise(MHParseNode *p, MHEngine *engine)
00819 {
00820     MHElemAction::Initialise(p, engine);
00821     m_Index.Initialise(p->GetArgN(1), engine);
00822     m_Item.Initialise(p->GetArgN(2), engine);
00823 }
00824 
00825 void MHAddItem::PrintArgs(FILE *fd, int) const
00826 {
00827     m_Index.PrintMe(fd, 0);
00828     m_Item.PrintMe(fd, 0);
00829 }
00830 
00831 void MHAddItem::Perform(MHEngine *engine)
00832 {
00833     MHObjectRef item;
00834     m_Item.GetValue(item, engine);
00835     Target(engine)->AddItem(m_Index.GetValue(engine), engine->FindObject(item), engine);
00836 }
00837 
00838 void MHGetListActionData::Initialise(MHParseNode *p, MHEngine *engine)
00839 {
00840     MHElemAction::Initialise(p, engine);
00841     m_Index.Initialise(p->GetArgN(1), engine);
00842     m_Result.Initialise(p->GetArgN(2), engine);
00843 }
00844 
00845 void MHGetListActionData::PrintArgs(FILE *fd, int) const
00846 {
00847     m_Index.PrintMe(fd, 0);
00848     m_Result.PrintMe(fd, 0);
00849 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends