Skip to content

Commit 6a039a8

Browse files
committed
Add timescale zooming when Cmd+mouse-drag on timescale
1 parent d04adb4 commit 6a039a8

2 files changed

Lines changed: 178 additions & 35 deletions

File tree

Source/Plugins/LfpDisplayNodeAlpha/LfpDisplayCanvas.cpp

Lines changed: 166 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ LfpDisplayCanvas::LfpDisplayCanvas(LfpDisplayNode* processor_) :
5353

5454
viewport = new LfpViewport(this);
5555
lfpDisplay = new LfpDisplay(this, viewport);
56-
timescale = new LfpTimescale(this);
56+
timescale = new LfpTimescale(this, lfpDisplay);
5757
options = new LfpDisplayOptions(this, timescale, lfpDisplay, processor);
5858

5959
lfpDisplay->options = options;
@@ -1370,6 +1370,42 @@ void LfpDisplayOptions::buttonClicked(Button* b)
13701370

13711371
}
13721372

1373+
void LfpDisplayOptions::setTimebaseAndSelectionText(float timebase)
1374+
{
1375+
canvas->timebase = timebase;
1376+
1377+
if (canvas->timebase) // if timebase != 0
1378+
{
1379+
if (canvas->timebase < timebases[0].getFloatValue())
1380+
{
1381+
timebaseSelection->setSelectedId(1, dontSendNotification);
1382+
canvas->timebase = timebases[0].getFloatValue();
1383+
}
1384+
else if (canvas->timebase > timebases[timebases.size()-1].getFloatValue())
1385+
{
1386+
timebaseSelection->setSelectedId(timebases.size(), dontSendNotification);
1387+
canvas->timebase = timebases[timebases.size()-1].getFloatValue();
1388+
}
1389+
else{
1390+
timebaseSelection->setText(String(canvas->timebase, 1), dontSendNotification);
1391+
}
1392+
}
1393+
else
1394+
{
1395+
if (selectedSpread == 0)
1396+
{
1397+
timebaseSelection->setText(selectedTimebaseValue, dontSendNotification);
1398+
canvas->timebase = selectedTimebaseValue.getFloatValue();
1399+
}
1400+
else
1401+
{
1402+
timebaseSelection->setSelectedId(selectedTimebase,dontSendNotification);
1403+
canvas->timebase = timebases[selectedTimebase-1].getFloatValue();
1404+
}
1405+
1406+
}
1407+
}
1408+
13731409

13741410
void LfpDisplayOptions::comboBoxChanged(ComboBox* cb)
13751411
{
@@ -1386,37 +1422,38 @@ void LfpDisplayOptions::comboBoxChanged(ComboBox* cb)
13861422
}
13871423
else
13881424
{
1389-
canvas->timebase = cb->getText().getFloatValue();
1390-
1391-
if (canvas->timebase)
1392-
{
1393-
if (canvas->timebase < timebases[0].getFloatValue())
1394-
{
1395-
cb->setSelectedId(1,dontSendNotification);
1396-
canvas->timebase = timebases[0].getFloatValue();
1397-
}
1398-
else if (canvas->timebase > timebases[timebases.size()-1].getFloatValue())
1399-
{
1400-
cb->setSelectedId(timebases.size(),dontSendNotification);
1401-
canvas->timebase = timebases[timebases.size()-1].getFloatValue();
1402-
}
1403-
else
1404-
cb->setText(String(canvas->timebase,1), dontSendNotification);
1405-
}
1406-
else
1407-
{
1408-
if (selectedSpread == 0)
1409-
{
1410-
cb->setText(selectedTimebaseValue, dontSendNotification);
1411-
canvas->timebase = selectedTimebaseValue.getFloatValue();
1412-
}
1413-
else
1414-
{
1415-
cb->setSelectedId(selectedTimebase,dontSendNotification);
1416-
canvas->timebase = timebases[selectedTimebase-1].getFloatValue();
1417-
}
1418-
1419-
}
1425+
setTimebaseAndSelectionText(cb->getText().getFloatValue());
1426+
// canvas->timebase = cb->getText().getFloatValue();
1427+
//
1428+
// if (canvas->timebase)
1429+
// {
1430+
// if (canvas->timebase < timebases[0].getFloatValue())
1431+
// {
1432+
// cb->setSelectedId(1,dontSendNotification);
1433+
// canvas->timebase = timebases[0].getFloatValue();
1434+
// }
1435+
// else if (canvas->timebase > timebases[timebases.size()-1].getFloatValue())
1436+
// {
1437+
// cb->setSelectedId(timebases.size(),dontSendNotification);
1438+
// canvas->timebase = timebases[timebases.size()-1].getFloatValue();
1439+
// }
1440+
// else
1441+
// cb->setText(String(canvas->timebase,1), dontSendNotification);
1442+
// }
1443+
// else
1444+
// {
1445+
// if (selectedSpread == 0)
1446+
// {
1447+
// cb->setText(selectedTimebaseValue, dontSendNotification);
1448+
// canvas->timebase = selectedTimebaseValue.getFloatValue();
1449+
// }
1450+
// else
1451+
// {
1452+
// cb->setSelectedId(selectedTimebase,dontSendNotification);
1453+
// canvas->timebase = timebases[selectedTimebase-1].getFloatValue();
1454+
// }
1455+
//
1456+
// }
14201457
}
14211458
}
14221459
else if (cb == rangeSelection)
@@ -1799,7 +1836,9 @@ void LfpDisplayOptions::loadParameters(XmlElement* xml)
17991836
#pragma mark - LfpTimescale -
18001837
// -------------------------------------------------------------
18011838

1802-
LfpTimescale::LfpTimescale(LfpDisplayCanvas* c) : canvas(c)
1839+
LfpTimescale::LfpTimescale(LfpDisplayCanvas* c, LfpDisplay* lfpDisplay)
1840+
: canvas(c)
1841+
, lfpDisplay(lfpDisplay)
18031842
{
18041843

18051844
font = Font("Default", 16, Font::plain);
@@ -1831,6 +1870,100 @@ void LfpTimescale::paint(Graphics& g)
18311870

18321871
}
18331872

1873+
void LfpTimescale::mouseDrag(const juce::MouseEvent &e)
1874+
{
1875+
if (e.mods.isLeftButtonDown()) // double check that we initiate only for left click and hold
1876+
{
1877+
if (e.mods.isCommandDown()) // CTRL + drag -> change channel spacing
1878+
{
1879+
// lfpDisplay->options-
1880+
// init state in our track zooming info struct
1881+
if (!lfpDisplay->trackZoomInfo.isScrollingX)
1882+
{
1883+
lfpDisplay->trackZoomInfo.isScrollingX = true;
1884+
lfpDisplay->trackZoomInfo.timescaleStartScale = timebase;
1885+
// lfpDisplay->trackZoomInfo.zoomPivotRatioY = (getY() + e.getMouseDownY())/(float)lfpDisplay->getHeight();
1886+
// lfpDisplay->trackZoomInfo.zoomPivotRatioX = (getX() + e.getMouseDownX())/(float)lfpDisplay->getWidth();
1887+
// lfpDisplay->trackZoomInfo.zoomPivotViewportOffset = getPosition() + e.getMouseDownPosition() - canvas->viewport->getViewPosition();
1888+
1889+
}
1890+
1891+
float timescale = lfpDisplay->trackZoomInfo.timescaleStartScale;
1892+
float dTimescale=0;
1893+
int dragDeltaX = (e.getScreenPosition().getX() - e.getMouseDownScreenX()); // invert so drag up -> scale up
1894+
1895+
std::cout << dragDeltaX << std::endl;
1896+
if (dragDeltaX > 0)
1897+
{
1898+
dTimescale = 0.01 * dragDeltaX;
1899+
}
1900+
else
1901+
{
1902+
if (timescale > 0.25)
1903+
dTimescale = 0.01 * dragDeltaX;
1904+
}
1905+
1906+
if (timescale >= 1) // accelerate scrolling for large ranges
1907+
dTimescale *= 4;
1908+
1909+
if (timescale >= 5)
1910+
dTimescale *= 4;
1911+
1912+
if (timescale >= 10)
1913+
dTimescale *= 4;
1914+
1915+
// round dTimescale to the nearest 0.005 sec
1916+
dTimescale = ((dTimescale + (0.005/2)) / 0.005) * 0.005;
1917+
1918+
float newTimescale = timescale+dTimescale;
1919+
std::cout << "new timescale: " << newTimescale << std::endl;
1920+
if (newTimescale < 0.25) newTimescale = 0.250;
1921+
if (newTimescale > 20) newTimescale = 20;
1922+
std::cout << "new timescale: " << newTimescale << std::endl;
1923+
1924+
// don't bother updating if the new timebase is the same as the old (if clipped, for example)
1925+
if (timescale != newTimescale)
1926+
{
1927+
lfpDisplay->options->setTimebaseAndSelectionText(newTimescale);
1928+
setTimebase(canvas->timebase);
1929+
}
1930+
//
1931+
// // constrain the spread resizing to max and min values;
1932+
// if (newHeight < lfpDisplay->trackZoomInfo.minZoomHeight)
1933+
// {
1934+
// newHeight = lfpDisplay->trackZoomInfo.minZoomHeight;
1935+
// }
1936+
// else if (newHeight > lfpDisplay->trackZoomInfo.maxZoomHeight)
1937+
// {
1938+
// newHeight = lfpDisplay->trackZoomInfo.maxZoomHeight;
1939+
// }
1940+
//
1941+
// // set channel heights for all channel
1942+
// lfpDisplay->setChannelHeight(newHeight);
1943+
// lfpDisplay->setBounds(0,0,lfpDisplay->getWidth()-0, lfpDisplay->getChannelHeight()*lfpDisplay->drawableChannels.size()); // update height so that the scrollbar is correct
1944+
//
1945+
// canvas->viewport->setViewPositionProportionately(lfpDisplay->trackZoomInfo.zoomPivotRatioX, lfpDisplay->trackZoomInfo.zoomPivotRatioY);
1946+
//
1947+
// int newViewportY = lfpDisplay->trackZoomInfo.zoomPivotRatioY * lfpDisplay->getHeight() - lfpDisplay->trackZoomInfo.zoomPivotViewportOffset.getY();
1948+
// if (newViewportY < 0) newViewportY = 0; // make sure we don't adjust beyond the edge of the actual view
1949+
//
1950+
// canvas->viewport->setViewPosition(lfpDisplay->trackZoomInfo.zoomPivotRatioX, newViewportY);
1951+
//
1952+
// setTimebase(newHeight); // update combobox
1953+
//
1954+
// canvas->fullredraw = true;//issue full redraw - scrolling without modifier doesnt require a full redraw
1955+
}
1956+
}
1957+
}
1958+
1959+
void LfpTimescale::mouseUp(const MouseEvent &e)
1960+
{
1961+
if (e.mods.isLeftButtonDown())
1962+
{
1963+
lfpDisplay->trackZoomInfo.isScrollingX = false;
1964+
}
1965+
}
1966+
18341967
void LfpTimescale::setTimebase(float t)
18351968
{
18361969
timebase = t;

Source/Plugins/LfpDisplayNodeAlpha/LfpDisplayCanvas.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,9 @@ class LfpDisplayOptions : public Component,
250250
void comboBoxChanged(ComboBox* cb);
251251
void buttonClicked(Button* button);
252252

253+
/** Changes the timebase value used by LfpTimescale and LfpDisplayCanvas. */
254+
void setTimebaseAndSelectionText(float timebase);
255+
253256
/** Handles slider events for all editors. */
254257
void sliderValueChanged(Slider* sl);
255258

@@ -394,16 +397,23 @@ class LfpDisplayOptions : public Component,
394397
class LfpTimescale : public Component
395398
{
396399
public:
397-
LfpTimescale(LfpDisplayCanvas*);
400+
LfpTimescale(LfpDisplayCanvas*, LfpDisplay*);
398401
~LfpTimescale();
399402

400403
void paint(Graphics& g);
404+
405+
/** Handles the drag to zoom feature on the timescale. The display must
406+
be paused to zoom */
407+
virtual void mouseDrag(const MouseEvent &e) override;
408+
409+
virtual void mouseUp(const MouseEvent &e) override;
401410

402411
void setTimebase(float t);
403412

404413
private:
405414

406415
LfpDisplayCanvas* canvas;
416+
LfpDisplay* lfpDisplay;
407417

408418
float timebase;
409419

@@ -568,7 +578,7 @@ class LfpDisplay : public Component
568578
bool isScrollingX = false;
569579
bool isScrollingY = false;
570580
int componentStartHeight; // a cache for the dimensions of a component during drag events
571-
int componentStartWidth;
581+
float timescaleStartScale; // a cache for the timescale size during drag events
572582
float zoomPivotRatioX; // a cache for calculating the anchor point when adjusting viewport
573583
float zoomPivotRatioY;
574584
Point<int> zoomPivotViewportOffset; // similar to above, but pixel-wise offset

0 commit comments

Comments
 (0)