123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568 |
- ////////////////////////////////////////////////////////////////////////////////
- //
- // Copyright 2016 RWS Inc, All Rights Reserved
- //
- // This program is free software; you can redistribute it and/or modify
- // it under the terms of version 2 of the GNU General Public License as published by
- // the Free Software Foundation
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License along
- // with this program; if not, write to the Free Software Foundation, Inc.,
- // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- //
- //////////////////////////////////////////////////////////////////////////////
- //
- // MultiBtn.cpp
- //
- // History:
- // 04/10/97 JMI Started this using RPushBtn as a template.
- //
- // 04/17/97 JMI Added Load and Save components.
- //
- // 04/22/97 JMI Added NextState().
- // CursorEvent() now uses NextState().
- // Also, DrawBackgroundRes() now chooses the image indexed
- // by m_sState instead of m_sState + 1.
- //
- // 09/25/97 JMI ReadMembers() was not clearing states that had no
- // corresponding images which, since SetNumStates()
- // preserves existing state images, could result in old
- // images persisting through loads that contained no image
- // for that state.
- // Also, now, in file version 7, reads and writes the
- // current state.
- //
- //////////////////////////////////////////////////////////////////////////////
- //
- // This a GUI item that is based on RBtn.
- // This overrides CursorEvent() to get information about where a click in its
- // RHot occurred.
- // This overrides Compose() to add text.
- //
- // Enhancements/Uses:
- // To change the look of a button when pressed, you may want to override the
- // Compose() or DrawBorder() in a derived class.
- // To get a callback on a click/release pair in the button, set m_bcUser.
- //
- //////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////
- // Headers.
- //////////////////////////////////////////////////////////////////////////////
- #include "Blue.h"
- #ifdef PATHS_IN_INCLUDES
- #include "ORANGE/GUI/MultiBtn.h"
- #else
- #include "multibtn.h"
- #endif // PATHS_IN_INCLUDES
- //////////////////////////////////////////////////////////////////////////////
- // Module specific macros.
- //////////////////////////////////////////////////////////////////////////////
- // Sets val to def if val is -1.
- #define DEF(val, def) ((val == -1) ? def : val)
- //////////////////////////////////////////////////////////////////////////////
- // Module specific typedefs.
- //////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////
- // Module specific (static) variables.
- //////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////
- // Construction/Destruction.
- //////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////
- //
- // Default constructor.
- //
- //////////////////////////////////////////////////////////////////////////////
- RMultiBtn::RMultiBtn()
- {
- // Override RGuiItem's/RBtn's defaults.
- m_type = MultiBtn; // Indicates type of GUI item.
- // Initialize RMultiBtn members.
- m_sState = 0; // The button's current state, 0..m_sNumStates - 1.
- m_sNumStates = 0; // Number of button states.
- m_papimStates = NULL; // Ptr to array of m_sNumStates ptrs to button
- // state images.
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Destructor.
- //
- //////////////////////////////////////////////////////////////////////////////
- RMultiBtn::~RMultiBtn()
- {
- DestroyStates();
- }
- ////////////////////////////////////////////////////////////////////////
- // Methods.
- ////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////
- //
- // Cursor event notification.
- // Events in event area.
- // (virtual).
- //
- ////////////////////////////////////////////////////////////////////////
- void RMultiBtn::CursorEvent( // Returns nothing.
- RInputEvent* pie) // In: Most recent user input event.
- // Out: pie->sUsed = TRUE, if used.
- {
- switch (pie->sEvent)
- {
- case RSP_MB0_DOUBLECLICK:
- case RSP_MB0_RELEASED:
- // If we were clicked in . . .
- if (m_sPressed != FALSE)
- {
- // Do change of state right away so user callback gets the new
- // value.
- // If within event area . . .
- if ( pie->sPosX >= m_sEventAreaX && pie->sPosX < m_sEventAreaX + m_sEventAreaW
- && pie->sPosY >= m_sEventAreaY && pie->sPosY < m_sEventAreaY + m_sEventAreaH)
- {
- // Change state.
- NextState();
- }
- }
- break;
- }
- // Call base.
- RGuiItem::CursorEvent(pie);
- switch (pie->sEvent)
- {
- case RSP_MB0_DOUBLECLICK:
- case RSP_MB0_PRESSED:
- // Always recompose on press, since there's so many possibilities
- // with this button.
- Compose();
- // Note that we used it.
- pie->sUsed = TRUE;
- break;
- case RSP_MB0_RELEASED:
- // Always recompose on release, since there's so many possibilities
- // with this button.
- Compose();
- // Note that we used it.
- pie->sUsed = TRUE;
- break;
- }
- }
- ////////////////////////////////////////////////////////////////////////
- // Draw background resource, if one is specified.
- // Utilizes base class version to place and BLiT the resource.
- // (virtual).
- ////////////////////////////////////////////////////////////////////////
- void RMultiBtn::DrawBackgroundRes( // Returns nothing.
- RImage* pim /*= NULL*/) // Dest image, uses m_im, if NULL.
- {
- // Store old bkd res.
- RImage* pimBkdRes = m_pimBkdRes;
- // If we have any states . . .
- if (m_papimStates != NULL)
- {
- // Choose proper image.
- if (m_sPressed == FALSE)
- {
- // If the state is available . . .
- if (m_sState <= m_sNumStates)
- {
- // Get the state.
- m_pimBkdRes = m_papimStates[m_sState];
- }
- }
- else
- {
- // Get the pressed feedback.
- m_pimBkdRes = m_papimStates[0];
- }
- }
- // Call base.
- RBtn::DrawBackgroundRes(pim);
- // Restore bkd res.
- m_pimBkdRes = pimBkdRes;
- }
- ////////////////////////////////////////////////////////////////////////
- // Set number of states.
- // This will clear all existing state images.
- ////////////////////////////////////////////////////////////////////////
- short RMultiBtn::SetNumStates( // Returns 0 on success.
- short sNumStates) // In: New number of states.
- {
- short sRes = 0; // Assume success.
- // Allocate an array of image ptrs and clear them all . . .
- RImage** papimNewStates = new RImage*[sNumStates + 1];
- if (papimNewStates != NULL)
- {
- // Clear all the ptrs to NULL.
- memset(papimNewStates, 0, sizeof(RImage*) * (sNumStates + 1));
- // If there was an old array . . .
- if (m_papimStates != NULL)
- {
- // Copy any currently valid ptrs within new range.
- short i;
- for (i = 0; i <= sNumStates && i <= m_sNumStates; i++)
- {
- // Copy entry.
- papimNewStates[i] = m_papimStates[i];
- // Clear entry so it is not deleted.
- m_papimStates[i] = NULL;
- }
- // Destroy any current states plus array.
- DestroyStates();
- }
- // Store the new number of states.
- m_sNumStates = sNumStates;
- // Store new arrray.
- m_papimStates = papimNewStates;
- }
- else
- {
- TRACE("SetNumStates(): Failed to allocate new array of Image ptrs.\n");
- sRes = -1;
- }
- return sRes;
- }
- ////////////////////////////////////////////////////////////////////////
- // Set button state or feedback state image.
- ////////////////////////////////////////////////////////////////////////
- short RMultiBtn::SetState( // Returns 0 on success.
- RImage* pim, // In: Image for state sState.
- short sState) // In: State to update (0 == feedback state,
- // 1..n == state number).
- {
- short sRes = 0; // Assume success.
- if (m_papimStates == NULL || sState >= m_sNumStates)
- {
- sRes = SetNumStates(sState);
- }
- // If successful so far . . .
- if (sRes == 0)
- {
- // Clear current value.
- delete m_papimStates[sState];
- // Allocate new one . . .
- m_papimStates[sState] = new RImage;
- if (m_papimStates[sState] != NULL)
- {
- // Copy specified image.
- *(m_papimStates[sState]) = *pim;
- }
- else
- {
- TRACE("SetState(): Failed to allocate new RImage.\n");
- sRes = -1;
- }
- }
- return sRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- // Set button state or feedback state image.
- // The feedback state image is always the last image (m_sNumStates).
- //////////////////////////////////////////////////////////////////////////////
- short RMultiBtn::SetState( // Returns 0 on success.
- char* pszImageName, // In: File name of image for state sState.
- short sState) // In: State to update (0 == feedback state,
- // 1..n == state number).
- {
- short sRes = 0; // Assume success.
- RImage im;
- if (RFileEZLoad(&im, pszImageName, "rb", RFile::LittleEndian) == 0)
- {
- sRes = SetState(&im, sState);
- }
- else
- {
- TRACE("SetState(): RFileEZLoad() failed for \"%s\".\n", pszImageName);
- sRes = -1;
- }
-
- return sRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- // Clear button state or feedback state image.
- // The feedback state image is always the first image.
- //////////////////////////////////////////////////////////////////////////////
- void RMultiBtn::ClearState( // Returns nothing.
- short sState) // In: State to clear (0 == feedback state,
- // 1..n == state number).
- {
- if (sState >= 0 && sState <= m_sNumStates)
- {
- if (m_papimStates != NULL)
- {
- // State be gone. Safe for already deallocated states as long as
- // they're NULL.
- delete m_papimStates[sState];
- m_papimStates[sState] = NULL;
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////////
- // Go to the next logical state.
- //////////////////////////////////////////////////////////////////////////////
- short RMultiBtn::NextState(void) // Returns new state.
- {
- if (m_sNumStates > 0)
- {
- m_sState = (m_sState % m_sNumStates) + 1;
- }
- else
- {
- m_sState = 0;
- }
- return m_sState;
- }
- //////////////////////////////////////////////////////////////////////////////
- // Querries.
- //////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////
- // Get the current image for the specified state.
- //////////////////////////////////////////////////////////////////////////////
- RImage* RMultiBtn::GetState( // Returns image, if available; NULL, otherwise.
- short sState) // In: State to get (0 == feedback state,
- // 1..n == state number).
- {
- RImage* pimRes = NULL; // Assume not available.
- if (sState >= 0 && sState <= m_sNumStates)
- {
- if (m_papimStates != NULL)
- {
- pimRes = m_papimStates[sState];
- }
- }
- return pimRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- // Internal functions.
- //////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////
- // Destroys current state bitmaps.
- //////////////////////////////////////////////////////////////////////////////
- void RMultiBtn::DestroyStates(void) // Returns nothing.
- {
- if (m_papimStates != NULL)
- {
- short i;
- for (i = 0; i <= m_sNumStates; i++)
- {
- delete m_papimStates[i];
- }
- delete []m_papimStates;
- m_sNumStates = 0;
- }
- }
- ////////////////////////////////////////////////////////////////////////
- // Read item's members from file.
- // (virtual/protected (overriden here)).
- ////////////////////////////////////////////////////////////////////////
- short RMultiBtn::ReadMembers( // Returns 0 on success.
- RFile* pfile, // File to read from.
- U32 u32Version) // File format version to use.
- {
- short sRes = 0; // Assume success.
- // Invoke base class to read base members.
- sRes = RBtn::ReadMembers(pfile, u32Version);
- // If okay so far . . .
- if (sRes == 0)
- {
- ASSERT(pfile != NULL);
- ASSERT(pfile->IsOpen() != FALSE);
-
- // Switch on version.
- switch (u32Version)
- {
- default:
- // Insert additional version numbers here!
- case 7:
- pfile->Read(&m_sState);
- case 6:
- case 5:
- case 4:
- case 3:
- case 2:
- case 1:
- {
- short sNumStates = 0; // Safety.
- // Read this class's members.
- pfile->Read(&sNumStates);
- // Set number of states.
- if (SetNumStates(sNumStates) == 0)
- {
- // Read all the images.
- short sCurState;
- short sImageForState;
- for (sCurState = 0; sCurState <= m_sNumStates && sRes == 0; sCurState++)
- {
- pfile->Read(&sImageForState);
- if (sImageForState != FALSE)
- {
- // There is an image. Load it.
- RImage imState;
- if (imState.Load(pfile) == 0)
- {
- // Set that state.
- if (SetState(&imState, sCurState) == 0)
- {
- // Successfully loaded and set state image.
- }
- else
- {
- TRACE("ReadMembers9): SetState() failed for state #%d.\n", sCurState);
- sRes = -3;
- }
- }
- else
- {
- TRACE("ReadMembers(): GetState() failed for state #%d.\n", sCurState);
- sRes = -2;
- }
- }
- else
- {
- // Make sure the state is clear.
- ClearState(sCurState);
- }
- }
- }
- else
- {
- TRACE("ReadMembers(): SetNumStates() failed.\n");
- sRes = -1;
- }
- }
- case 0: // In version 0, only base class RGuiItem members were stored.
- // If successful . . .
- if (pfile->Error() == FALSE)
- {
- // Success.
- }
- else
- {
- TRACE("ReadMembers(): Error reading RMultiBtn members.\n");
- sRes = -1;
- }
- break;
- }
- }
- return sRes;
- }
- ////////////////////////////////////////////////////////////////////////
- // Write item's members to file.
- // (virtual/protected (overriden here)).
- ////////////////////////////////////////////////////////////////////////
- short RMultiBtn::WriteMembers( // Returns 0 on success.
- RFile* pfile) // File to write to.
- {
- short sRes = 0; // Assume success.
- // Invoke base class to read base members.
- sRes = RBtn::WriteMembers(pfile);
- // If okay so far . . .
- if (sRes == 0)
- {
- ASSERT(pfile != NULL);
- ASSERT(pfile->IsOpen() != FALSE);
-
- // Write this class's members.
- pfile->Write(m_sState);
- pfile->Write(m_sNumStates);
- // Write all the images.
- short sCurState;
- for (sCurState = 0; sCurState <= m_sNumStates && sRes == 0; sCurState++)
- {
- // If there is a bitmap for this state . . .
- RImage* pimState = GetState(sCurState);
- if (pimState != NULL)
- {
- // There is an image. Write flag indicating such.
- pfile->Write((short)TRUE);
- // Write image.
- sRes = pimState->Save(pfile);
- }
- else
- {
- // No image. Write flag indicating such.
- pfile->Write((short)FALSE);
- }
- }
- // If successful . . .
- if (pfile->Error() == FALSE)
- {
- // Success.
- }
- else
- {
- TRACE("WriteMembers(): Error writing RMultiBtn members.\n");
- sRes = -1;
- }
- }
- return sRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- // EOF
- //////////////////////////////////////////////////////////////////////////////
|