Chris@1118: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@1118: Chris@1118: /* Chris@1118: Sonic Visualiser Chris@1118: An audio file viewer and annotation editor. Chris@1118: Centre for Digital Music, Queen Mary, University of London. Chris@1118: Chris@1118: This program is free software; you can redistribute it and/or Chris@1118: modify it under the terms of the GNU General Public License as Chris@1118: published by the Free Software Foundation; either version 2 of the Chris@1118: License, or (at your option) any later version. See the file Chris@1118: COPYING included with this distribution for more information. Chris@1118: */ Chris@1118: Chris@1118: #ifndef SCROLLABLE_MAG_RANGE_CACHE_H Chris@1118: #define SCROLLABLE_MAG_RANGE_CACHE_H Chris@1118: Chris@1118: #include "base/BaseTypes.h" Chris@1118: #include "base/MagnitudeRange.h" Chris@1118: Chris@1118: #include "LayerGeometryProvider.h" Chris@1118: Chris@1118: /** Chris@1118: * A cached set of magnitude range records for a view that scrolls Chris@1118: * horizontally, such as a spectrogram. The cache object holds a Chris@1118: * magnitude range per column of the view, can report width (likely Chris@1118: * the same as the underlying view, but it's the caller's Chris@1118: * responsibility to set the size appropriately), can scroll the set Chris@1118: * of ranges, and can report and update which columns have had a range Chris@1118: * specified. Chris@1118: * Chris@1118: * The only way to *update* the valid area in a cache is to update the Chris@1118: * magnitude range for a column using the sampleColumn call. Chris@1118: */ Chris@1118: class ScrollableMagRangeCache Chris@1118: { Chris@1118: public: Chris@1118: ScrollableMagRangeCache() : Chris@1325: m_startFrame(0) Chris@1118: {} Chris@1118: Chris@1118: void invalidate() { Chris@1266: m_ranges = std::vector(m_ranges.size()); Chris@1118: } Chris@1118: Chris@1118: int getWidth() const { Chris@1266: return int(m_ranges.size()); Chris@1118: } Chris@1118: Chris@1118: /** Chris@1118: * Set the width of the cache in columns. If the new size differs Chris@1118: * from the current size, the cache is invalidated. Chris@1118: */ Chris@1118: void resize(int newWidth) { Chris@1118: if (getWidth() != newWidth) { Chris@1266: m_ranges = std::vector(newWidth); Chris@1118: } Chris@1118: } Chris@1266: Chris@1325: ZoomLevel getZoomLevel() const { Chris@1266: return m_zoomLevel; Chris@1118: } Chris@1118: Chris@1118: /** Chris@1118: * Set the zoom level. If the new zoom level differs from the Chris@1118: * current one, the cache is invalidated. (Determining whether to Chris@1118: * invalidate the cache here is the only thing the zoom level is Chris@1118: * used for.) Chris@1118: */ Chris@1325: void setZoomLevel(ZoomLevel zoom) { Chris@1325: using namespace std::rel_ops; Chris@1118: if (m_zoomLevel != zoom) { Chris@1118: m_zoomLevel = zoom; Chris@1118: invalidate(); Chris@1118: } Chris@1118: } Chris@1118: Chris@1118: sv_frame_t getStartFrame() const { Chris@1266: return m_startFrame; Chris@1118: } Chris@1118: Chris@1118: /** Chris@1118: * Set the start frame. If the new start frame differs from the Chris@1118: * current one, the cache is invalidated. To scroll, i.e. to set Chris@1118: * the start frame while retaining cache validity where possible, Chris@1118: * use scrollTo() instead. Chris@1118: */ Chris@1118: void setStartFrame(sv_frame_t frame) { Chris@1118: if (m_startFrame != frame) { Chris@1118: m_startFrame = frame; Chris@1118: invalidate(); Chris@1118: } Chris@1118: } Chris@1118: Chris@1118: bool isColumnSet(int column) const { Chris@1266: return in_range_for(m_ranges, column) && m_ranges.at(column).isSet(); Chris@1118: } Chris@1119: Chris@1119: bool areColumnsSet(int x, int count) const { Chris@1266: for (int i = 0; i < count; ++i) { Chris@1266: if (!isColumnSet(x + i)) return false; Chris@1266: } Chris@1266: return true; Chris@1119: } Chris@1118: Chris@1119: /** Chris@1119: * Get the magnitude range for a single column. Chris@1119: */ Chris@1119: MagnitudeRange getRange(int column) const { Chris@1266: return m_ranges.at(column); Chris@1118: } Chris@1118: Chris@1118: /** Chris@1119: * Get the magnitude range for a range of columns. Chris@1119: */ Chris@1122: MagnitudeRange getRange(int x, int count) const; Chris@1119: Chris@1119: /** Chris@1118: * Set the new start frame for the cache, according to the Chris@1118: * geometry of the supplied LayerGeometryProvider, if possible Chris@1118: * also moving along any existing valid data within the cache so Chris@1118: * that it continues to be valid for the new start frame. Chris@1118: */ Chris@1118: void scrollTo(const LayerGeometryProvider *v, sv_frame_t newStartFrame); Chris@1118: Chris@1118: /** Chris@1120: * Update a column in the cache, by column index. (Column zero is Chris@1120: * the first column in the cache, it has nothing to do with any Chris@1120: * underlying model that the cache may be used with.) Chris@1118: */ Chris@1120: void sampleColumn(int column, const MagnitudeRange &r); Chris@1118: Chris@1118: private: Chris@1118: std::vector m_ranges; Chris@1118: sv_frame_t m_startFrame; Chris@1325: ZoomLevel m_zoomLevel; Chris@1118: }; Chris@1118: Chris@1118: #endif