/* * DISTRHO Plugin Framework (DPF) * Copyright (C) 2012-2021 Filipe Coelho * * Permission to use, copy, modify, and/or distribute this software for any purpose with * or without fee is hereby granted, provided that the above copyright notice and this * permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "DistrhoUI.hpp" #include "extra/String.hpp" #include "DistrhoPluginInfo.h" #include "NanoButton.hpp" START_NAMESPACE_DISTRHO using DGL_NAMESPACE::Button; using DGL_NAMESPACE::ButtonEventHandler; using DGL_NAMESPACE::SubWidget; const char* kStateKeys[kStateCount] = { "file1", "file2", "file3", }; // ----------------------------------------------------------------------------------------------------------- inline void setupButton(Button& btn, const int y) { btn.setAbsolutePos(5, y); btn.setLabel("Open..."); btn.setSize(100, 30); } class FileHandlingExampleUI : public UI, public ButtonEventHandler::Callback { public: static const uint kInitialWidth = 600; static const uint kInitialHeight = 350; FileHandlingExampleUI() : UI(kInitialWidth, kInitialHeight), fButton1(this, this), fButton2(this, this), fButton3(this, this), fScale(1.0f) { std::memset(fParameters, 0, sizeof(fParameters)); std::memset(fStrBuf, 0, sizeof(fStrBuf)); setupButton(fButton1, 5); setupButton(fButton2, 105); setupButton(fButton3, 205); #ifdef DGL_NO_SHARED_RESOURCES createFontFromFile("sans", "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf"); #else loadSharedResources(); #endif setGeometryConstraints(kInitialWidth, kInitialHeight, false); } protected: /* -------------------------------------------------------------------------------------------------------- * DSP/Plugin Callbacks */ /** A parameter has changed on the plugin side.@n This is called by the host to inform the UI about parameter changes. */ void parameterChanged(uint32_t index, float value) override { fParameters[index] = value; repaint(); } /** A state has changed on the plugin side.@n This is called by the host to inform the UI about state changes. */ void stateChanged(const char* key, const char* value) override { States stateId = kStateCount; /**/ if (std::strcmp(key, "file1") == 0) stateId = kStateFile1; else if (std::strcmp(key, "file2") == 0) stateId = kStateFile2; else if (std::strcmp(key, "file3") == 0) stateId = kStateFile3; if (stateId == kStateCount) return; fState[stateId] = value; repaint(); } /* -------------------------------------------------------------------------------------------------------- * Widget Callbacks */ /** The NanoVG drawing function. */ void onNanoDisplay() override { const float lineHeight = 20 * fScale; float y; fontSize(15.0f * fScale); textLineHeight(lineHeight); // --------------------------------------------------------------------------------------- // File 1 y = 45.0f * fScale; if (fState[kStateFile1].isNotEmpty()) { drawLeft(0.0f, y, "Name:"); drawRight(0.0f, y, fState[kStateFile1]); y += lineHeight; drawLeft(0.0f, y, "Size:"); drawRight(0.0f, y, getTextBufFileSize(fParameters[kParameterFileSize1])); y += lineHeight; } else { drawLeft(0.0f, y, "No file loaded"); } // --------------------------------------------------------------------------------------- // File 2 y = 145.0f * fScale; if (fState[kStateFile2].isNotEmpty()) { drawLeft(0.0f, y, "Name:"); drawRight(0.0f, y, fState[kStateFile2]); y += lineHeight; drawLeft(0.0f, y, "Size:"); drawRight(0.0f, y, getTextBufFileSize(fParameters[kParameterFileSize2])); y += lineHeight; } else { drawLeft(0.0f, y, "No file loaded"); } // --------------------------------------------------------------------------------------- // File 3 y = 245.0f * fScale; if (fState[kStateFile3].isNotEmpty()) { drawLeft(0.0f, y, "Name:"); drawRight(0.0f, y, fState[kStateFile3]); y += lineHeight; drawLeft(0.0f, y, "Size:"); drawRight(0.0f, y, getTextBufFileSize(fParameters[kParameterFileSize3])); y += lineHeight; } else { drawLeft(0.0f, y, "No file loaded"); } } void onResize(const ResizeEvent& ev) override { fScale = static_cast(ev.size.getHeight())/kInitialHeight; fButton1.setAbsolutePos(5*fScale, 5*fScale); fButton2.setAbsolutePos(5*fScale, 105*fScale); fButton3.setAbsolutePos(5*fScale, 205*fScale); fButton1.setSize(100*fScale, 30*fScale); fButton2.setSize(100*fScale, 30*fScale); fButton3.setSize(100*fScale, 30*fScale); fButton1.setFontScale(fScale); fButton2.setFontScale(fScale); fButton3.setFontScale(fScale); UI::onResize(ev); } void buttonClicked(SubWidget* const widget, int) override { States stateId; /**/ if (widget == &fButton1) stateId = kStateFile1; else if (widget == &fButton2) stateId = kStateFile2; else if (widget == &fButton3) stateId = kStateFile3; else return; requestStateFile(kStateKeys[stateId]); } // ------------------------------------------------------------------------------------------------------- private: // Parameters float fParameters[kParameterCount]; // State (files) String fState[kStateCount]; Button fButton1, fButton2, fButton3; // UI stuff float fScale; // temp buf for text char fStrBuf[0xff]; // helpers for putting text into fStrBuf and returning it const char* getTextBufFileSize(const float value) { /**/ if (value > 1024*1024) std::snprintf(fStrBuf, 0xfe, "%.2f GiB", value/(1024*1024)); else if (value > 1024) std::snprintf(fStrBuf, 0xfe, "%.2f MiB", value/1024); else std::snprintf(fStrBuf, 0xfe, "%.2f KiB", value); return fStrBuf; } // helpers for drawing text void drawLeft(const float x, const float y, const char* const text) { beginPath(); fillColor(200, 200, 200); textAlign(ALIGN_RIGHT|ALIGN_TOP); textBox(x, y, 100 * fScale, text); closePath(); } void drawRight(const float x, const float y, const char* const text) { beginPath(); fillColor(255, 255, 255); textAlign(ALIGN_LEFT|ALIGN_TOP); textBox(x + (105 * fScale), y, (kInitialWidth - x) * fScale, text); closePath(); } /** Set our UI class as non-copyable and add a leak detector just in case. */ DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FileHandlingExampleUI) }; /* ------------------------------------------------------------------------------------------------------------ * UI entry point, called by DPF to create a new UI instance. */ UI* createUI() { return new FileHandlingExampleUI(); } // ----------------------------------------------------------------------------------------------------------- END_NAMESPACE_DISTRHO