| @@ -53,8 +53,8 @@ | |||
| // BEGIN SECTION A | |||
| #define JUCE_DISPLAY_SPLASH_SCREEN 1 | |||
| #define JUCE_REPORT_APP_USAGE 1 | |||
| #define JUCE_DISPLAY_SPLASH_SCREEN 0 | |||
| #define JUCE_REPORT_APP_USAGE 0 | |||
| // END SECTION A | |||
| @@ -2,8 +2,8 @@ | |||
| <JUCERPROJECT id="M70qfTRRk" name="Projucer" projectType="guiapp" juceFolder="../../juce" | |||
| jucerVersion="5.0.0" version="5.0.0" bundleIdentifier="com.juce.theprojucer" | |||
| defines="" includeBinaryInAppConfig="1" displaySplashScreen="1" | |||
| reportAppUsage="1" useDarkSplashScreen="1" splashScreenColour="Dark"> | |||
| defines="" includeBinaryInAppConfig="1" splashScreenColour="Dark" | |||
| displaySplashScreen="0" reportAppUsage="0"> | |||
| <EXPORTFORMATS> | |||
| <XCODE_MAC targetFolder="Builds/MacOSX" vstFolder="~/SDKs/vstsdk2.4" rtasFolder="~/SDKs/PT_80_SDK" | |||
| documentExtensions=".jucer" objCExtraSuffix="zkVtji" bigIcon="OCyr5F" | |||
| @@ -82,9 +82,13 @@ void ProjucerApplication::initialise (const String& commandLine) | |||
| initialiseBasics(); | |||
| if (commandLine.isNotEmpty()) | |||
| isRunningCommandLine = commandLine.isNotEmpty(); | |||
| licenseController = new LicenseController; | |||
| licenseController->addLicenseStatusChangedCallback (this); | |||
| if (isRunningCommandLine) | |||
| { | |||
| isRunningCommandLine = true; | |||
| const int appReturnCode = performCommandLine (commandLine); | |||
| if (appReturnCode != commandLineNotPerformed) | |||
| @@ -149,9 +153,8 @@ bool ProjucerApplication::initialiseLogger (const char* filePrefix) | |||
| void ProjucerApplication::handleAsyncUpdate() | |||
| { | |||
| licenseController = new LicenseController; | |||
| licenseController->addLicenseStatusChangedCallback (this); | |||
| licenseStateChanged (licenseController->getState()); | |||
| if (licenseController != nullptr) | |||
| licenseController->startWebviewIfNeeded(); | |||
| #if JUCE_MAC | |||
| PopupMenu extraAppleMenuItems; | |||
| @@ -175,6 +178,9 @@ void ProjucerApplication::initialiseWindows (const String& commandLine) | |||
| mainWindowList.reopenLastProjects(); | |||
| mainWindowList.createWindowIfNoneAreOpen(); | |||
| if (licenseController->getState().applicationUsageDataState == LicenseState::ApplicationUsageData::notChosenYet) | |||
| showApplicationUsageDataAgreementPopup(); | |||
| } | |||
| void ProjucerApplication::shutdown() | |||
| @@ -255,8 +261,12 @@ void ProjucerApplication::systemRequestedQuit() | |||
| //============================================================================== | |||
| void ProjucerApplication::licenseStateChanged (const LicenseState& state) | |||
| { | |||
| #if ! JUCER_ENABLE_GPL_MODE | |||
| if (state.type != LicenseState::Type::notLoggedIn | |||
| && state.type != LicenseState::Type::noLicenseChosenYet) | |||
| #else | |||
| ignoreUnused (state); | |||
| #endif | |||
| { | |||
| initialiseWindows (getCommandLineParameters()); | |||
| } | |||
| @@ -370,6 +380,7 @@ void ProjucerApplication::createFileMenu (PopupMenu& menu) | |||
| #if ! JUCE_MAC | |||
| menu.addCommandItem (commandManager, CommandIDs::showAboutWindow); | |||
| menu.addCommandItem (commandManager, CommandIDs::showAppUsageWindow); | |||
| menu.addCommandItem (commandManager, CommandIDs::showGlobalPreferences); | |||
| menu.addSeparator(); | |||
| menu.addCommandItem (commandManager, StandardApplicationCommandIDs::quit); | |||
| @@ -467,6 +478,7 @@ void ProjucerApplication::createToolsMenu (PopupMenu& menu) | |||
| void ProjucerApplication::createExtraAppleMenuItems (PopupMenu& menu) | |||
| { | |||
| menu.addCommandItem (commandManager, CommandIDs::showAboutWindow); | |||
| menu.addCommandItem (commandManager, CommandIDs::showAppUsageWindow); | |||
| menu.addSeparator(); | |||
| menu.addCommandItem (commandManager, CommandIDs::showGlobalPreferences); | |||
| } | |||
| @@ -508,10 +520,11 @@ void ProjucerApplication::handleMainMenuCommand (int menuItemID) | |||
| lookAndFeel.setupColours(); | |||
| mainWindowList.sendLookAndFeelChange(); | |||
| if (utf8Window != nullptr) utf8Window->sendLookAndFeelChange(); | |||
| if (svgPathWindow != nullptr) svgPathWindow->sendLookAndFeelChange(); | |||
| if (globalPreferencesWindow != nullptr) globalPreferencesWindow->sendLookAndFeelChange(); | |||
| if (aboutWindow != nullptr) aboutWindow->sendLookAndFeelChange(); | |||
| if (utf8Window != nullptr) utf8Window->sendLookAndFeelChange(); | |||
| if (svgPathWindow != nullptr) svgPathWindow->sendLookAndFeelChange(); | |||
| if (globalPreferencesWindow != nullptr) globalPreferencesWindow->sendLookAndFeelChange(); | |||
| if (aboutWindow != nullptr) aboutWindow->sendLookAndFeelChange(); | |||
| if (applicationUsageDataWindow != nullptr) applicationUsageDataWindow->sendLookAndFeelChange(); | |||
| } | |||
| else | |||
| { | |||
| @@ -532,6 +545,7 @@ void ProjucerApplication::getAllCommands (Array <CommandID>& commands) | |||
| CommandIDs::showUTF8Tool, | |||
| CommandIDs::showSVGPathTool, | |||
| CommandIDs::showAboutWindow, | |||
| CommandIDs::showAppUsageWindow, | |||
| CommandIDs::loginLogout }; | |||
| commands.addArray (ids, numElementsInArray (ids)); | |||
| @@ -578,6 +592,10 @@ void ProjucerApplication::getCommandInfo (CommandID commandID, ApplicationComman | |||
| result.setInfo ("About Projucer", "Shows the Projucer's 'About' page.", CommandCategories::general, 0); | |||
| break; | |||
| case CommandIDs::showAppUsageWindow: | |||
| result.setInfo ("Application Usage Data", "Shows the application usage data agreement window", CommandCategories::general, 0); | |||
| break; | |||
| case CommandIDs::loginLogout: | |||
| { | |||
| bool isLoggedIn = false; | |||
| @@ -615,6 +633,7 @@ bool ProjucerApplication::perform (const InvocationInfo& info) | |||
| case CommandIDs::showSVGPathTool: showSVGPathDataToolWindow(); break; | |||
| case CommandIDs::showGlobalPreferences: AppearanceSettings::showGlobalPreferences (globalPreferencesWindow); break; | |||
| case CommandIDs::showAboutWindow: showAboutWindow(); break; | |||
| case CommandIDs::showAppUsageWindow: showApplicationUsageDataAgreementPopup(); break; | |||
| case CommandIDs::loginLogout: doLogout(); break; | |||
| default: return JUCEApplication::perform (info); | |||
| } | |||
| @@ -686,12 +705,28 @@ void ProjucerApplication::showAboutWindow() | |||
| if (aboutWindow != nullptr) | |||
| aboutWindow->toFront (true); | |||
| else | |||
| new FloatingToolWindow ("", | |||
| "aboutWindowPos", | |||
| new AboutWindowComponent(), aboutWindow, false, | |||
| new FloatingToolWindow ({}, {}, new AboutWindowComponent(), | |||
| aboutWindow, false, | |||
| 500, 300, 500, 300, 500, 300); | |||
| } | |||
| void ProjucerApplication::showApplicationUsageDataAgreementPopup() | |||
| { | |||
| if (applicationUsageDataWindow != nullptr) | |||
| applicationUsageDataWindow->toFront (true); | |||
| else | |||
| new FloatingToolWindow ("Application Usage Analytics", | |||
| {}, new ApplicationUsageDataWindowComponent (isPaidOrGPL()), | |||
| applicationUsageDataWindow, false, | |||
| 400, 300, 400, 300, 400, 300); | |||
| } | |||
| void ProjucerApplication::dismissApplicationUsageDataAgreementPopup() | |||
| { | |||
| if (applicationUsageDataWindow != nullptr) | |||
| applicationUsageDataWindow = nullptr; | |||
| } | |||
| //============================================================================== | |||
| struct FileWithTime | |||
| { | |||
| @@ -99,8 +99,8 @@ public: | |||
| void showSVGPathDataToolWindow(); | |||
| void showAboutWindow(); | |||
| void showLoginWindow(); | |||
| void showApplicationUsageDataAgreementPopup(); | |||
| void dismissApplicationUsageDataAgreementPopup(); | |||
| void updateAllBuildTabs(); | |||
| LatestVersionChecker* createVersionChecker() const; | |||
| @@ -124,7 +124,9 @@ public: | |||
| OpenDocumentManager openDocumentManager; | |||
| ScopedPointer<ApplicationCommandManager> commandManager; | |||
| ScopedPointer<Component> appearanceEditorWindow, globalPreferencesWindow, utf8Window, svgPathWindow, aboutWindow; | |||
| ScopedPointer<Component> appearanceEditorWindow, globalPreferencesWindow, utf8Window, | |||
| svgPathWindow, aboutWindow, applicationUsageDataWindow; | |||
| ScopedPointer<FileLogger> logger; | |||
| bool isRunningCommandLine; | |||
| @@ -49,6 +49,7 @@ namespace CommandIDs | |||
| showTranslationTool = 0x300022, | |||
| showSVGPathTool = 0x300023, | |||
| showAboutWindow = 0x300024, | |||
| showAppUsageWindow = 0x300025, | |||
| showProjectSettings = 0x300030, | |||
| showProjectTab = 0x300031, | |||
| @@ -34,6 +34,7 @@ | |||
| #include "../Utility/jucer_UTF8Component.h" | |||
| #include "../Utility/jucer_SVGPathDataComponent.h" | |||
| #include "../Utility/jucer_AboutWindowComponent.h" | |||
| #include "../Utility/jucer_ApplicationUsageDataWindowComponent.h" | |||
| #include "../Utility/jucer_FloatingToolWindow.h" | |||
| #include "../LiveBuildEngine/projucer_MessageIDs.h" | |||
| @@ -71,6 +71,23 @@ static LicenseState::Type getLicenseTypeFromValue (const String& d) | |||
| return LicenseState::Type::noLicenseChosenYet; | |||
| } | |||
| static const char* getApplicationUsageDataStateValue (LicenseState::ApplicationUsageData type) | |||
| { | |||
| switch (type) | |||
| { | |||
| case LicenseState::ApplicationUsageData::enabled: return "enabled"; | |||
| case LicenseState::ApplicationUsageData::disabled: return "disabled"; | |||
| default: return "notChosen"; | |||
| } | |||
| } | |||
| static LicenseState::ApplicationUsageData getApplicationUsageDataTypeFromValue (const String& value) | |||
| { | |||
| if (value == getApplicationUsageDataStateValue (LicenseState::ApplicationUsageData::enabled)) return LicenseState::ApplicationUsageData::enabled; | |||
| if (value == getApplicationUsageDataStateValue (LicenseState::ApplicationUsageData::disabled)) return LicenseState::ApplicationUsageData::disabled; | |||
| return LicenseState::ApplicationUsageData::notChosenYet; | |||
| } | |||
| //============================================================================== | |||
| struct LicenseController::ModalCompletionCallback : ModalComponentManager::Callback | |||
| { | |||
| @@ -83,15 +100,11 @@ struct LicenseController::ModalCompletionCallback : ModalComponentManager::Callb | |||
| //============================================================================== | |||
| LicenseController::LicenseController() | |||
| #if (! JUCER_ENABLE_GPL_MODE) | |||
| : state (licenseStateFromSettings (ProjucerApplication::getApp().settings->getGlobalProperties())) | |||
| #endif | |||
| { | |||
| #if JUCER_ENABLE_GPL_MODE | |||
| state.type = LicenseState::Type::GPL; | |||
| state.username = "GPL mode"; | |||
| #else | |||
| thread = new LicenseThread (*this, false); | |||
| #endif | |||
| } | |||
| @@ -101,6 +114,37 @@ LicenseController::~LicenseController() | |||
| closeWebview (-1); | |||
| } | |||
| LicenseState LicenseController::getState() const noexcept | |||
| { | |||
| LicenseState projucerState = state; | |||
| // if the user has never logged in before and the user is running from command line | |||
| // then we have no way to ask the user to log in, so fallback to GPL mode | |||
| if (guiNotInitialisedYet | |||
| && (state.type == LicenseState::Type::notLoggedIn | |||
| || state.type == LicenseState::Type::noLicenseChosenYet)) | |||
| { | |||
| projucerState.type = LicenseState::Type::GPL; | |||
| projucerState.username = "GPL mode"; | |||
| } | |||
| return projucerState; | |||
| } | |||
| void LicenseController::startWebviewIfNeeded() | |||
| { | |||
| if (guiNotInitialisedYet) | |||
| { | |||
| guiNotInitialisedYet = false; | |||
| listeners.call (&StateChangedCallback::licenseStateChanged, getState()); | |||
| } | |||
| #if ! JUCER_ENABLE_GPL_MODE | |||
| if (thread == nullptr) | |||
| thread = new LicenseThread (*this, false); | |||
| #endif | |||
| } | |||
| void LicenseController::logout() | |||
| { | |||
| jassert (MessageManager::getInstance()->isThisTheMessageThread()); | |||
| @@ -127,6 +171,15 @@ void LicenseController::chooseNewLicense() | |||
| #endif | |||
| } | |||
| void LicenseController::setApplicationUsageDataState (LicenseState::ApplicationUsageData newState) | |||
| { | |||
| if (state.applicationUsageDataState != newState) | |||
| { | |||
| state.applicationUsageDataState = newState; | |||
| updateState (state); | |||
| } | |||
| } | |||
| //============================================================================== | |||
| void LicenseController::closeWebview (int result) | |||
| { | |||
| @@ -198,7 +251,7 @@ void LicenseController::updateState (const LicenseState& newState) | |||
| state = newState; | |||
| licenseStateToSettings (state, props); | |||
| listeners.call (&StateChangedCallback::licenseStateChanged, state); | |||
| listeners.call (&StateChangedCallback::licenseStateChanged, getState()); | |||
| } | |||
| LicenseState LicenseController::licenseStateFromSettings (PropertiesFile& props) | |||
| @@ -208,10 +261,11 @@ LicenseState LicenseController::licenseStateFromSettings (PropertiesFile& props) | |||
| if (licenseXml != nullptr) | |||
| { | |||
| LicenseState result; | |||
| result.type = getLicenseTypeFromValue (licenseXml->getChildElementAllSubText ("type", {})); | |||
| result.username = licenseXml->getChildElementAllSubText ("username", {}); | |||
| result.email = licenseXml->getChildElementAllSubText ("email", {}); | |||
| result.authToken = licenseXml->getChildElementAllSubText ("authToken", {}); | |||
| result.type = getLicenseTypeFromValue (licenseXml->getChildElementAllSubText ("type", {})); | |||
| result.applicationUsageDataState = getApplicationUsageDataTypeFromValue (licenseXml->getChildElementAllSubText ("applicationUsageData", {})); | |||
| result.username = licenseXml->getChildElementAllSubText ("username", {}); | |||
| result.email = licenseXml->getChildElementAllSubText ("email", {}); | |||
| result.authToken = licenseXml->getChildElementAllSubText ("authToken", {}); | |||
| MemoryOutputStream imageData; | |||
| Base64::convertFromBase64 (imageData, licenseXml->getChildElementAllSubText ("avatar", {})); | |||
| @@ -227,14 +281,15 @@ void LicenseController::licenseStateToSettings (const LicenseState& state, Prope | |||
| { | |||
| props.removeValue ("license"); | |||
| if (state.type != LicenseState::Type::notLoggedIn | |||
| && state.username.isNotEmpty() && state.authToken.isNotEmpty()) | |||
| if (state.type != LicenseState::Type::notLoggedIn && state.username.isNotEmpty()) | |||
| { | |||
| XmlElement licenseXml ("license"); | |||
| if (auto* typeString = getLicenseStateValue (state.type)) | |||
| licenseXml.createNewChildElement ("type")->addTextElement (typeString); | |||
| licenseXml.createNewChildElement ("applicationUsageData")->addTextElement (getApplicationUsageDataStateValue (state.applicationUsageDataState)); | |||
| licenseXml.createNewChildElement ("username")->addTextElement (state.username); | |||
| licenseXml.createNewChildElement ("email") ->addTextElement (state.email); | |||
| @@ -44,7 +44,16 @@ struct LicenseState | |||
| pro | |||
| }; | |||
| enum class ApplicationUsageData | |||
| { | |||
| notChosenYet, | |||
| enabled, | |||
| disabled | |||
| }; | |||
| Type type = Type::notLoggedIn; | |||
| ApplicationUsageData applicationUsageDataState = ApplicationUsageData::notChosenYet; | |||
| String username; | |||
| String email; | |||
| String authToken; | |||
| @@ -71,10 +80,13 @@ public: | |||
| LicenseController(); | |||
| ~LicenseController(); | |||
| void startWebviewIfNeeded(); | |||
| //============================================================================== | |||
| const LicenseState& getState() const noexcept { return state; } | |||
| LicenseState getState() const noexcept; | |||
| void logout(); | |||
| void chooseNewLicense(); | |||
| void setApplicationUsageDataState (LicenseState::ApplicationUsageData newState); | |||
| //============================================================================== | |||
| void addLicenseStatusChangedCallback (StateChangedCallback* callback) { listeners.add (callback); } | |||
| @@ -103,6 +115,7 @@ private: | |||
| ScopedPointer<LicenseThread> thread; | |||
| LicenseWebview* licenseWebview = nullptr; | |||
| ListenerList<LicenseController::StateChangedCallback> listeners; | |||
| bool guiNotInitialisedYet = true; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LicenseController) | |||
| }; | |||
| @@ -374,7 +374,6 @@ private: | |||
| << "// [END_USER_CODE_SECTION]" << newLine; | |||
| out << newLine | |||
| << "//==============================================================================" << newLine | |||
| << "/*" << newLine | |||
| << " ==============================================================================" << newLine | |||
| << newLine | |||
| @@ -491,7 +491,7 @@ private: | |||
| { | |||
| if (LicenseController* controller = ProjucerApplication::getApp().licenseController) | |||
| { | |||
| auto& state = controller->getState(); | |||
| auto state = controller->getState(); | |||
| userSettingsButton->iconImage = state.avatar; | |||
| userSettingsButton->repaint(); | |||
| @@ -113,13 +113,19 @@ void Project::setMissingDefaultValues() | |||
| setTitle ("JUCE Project"); | |||
| { | |||
| auto defaultSplashScreenAndReporting = ! ProjucerApplication::getApp().isPaidOrGPL(); | |||
| auto defaultSplashScreen = ! ProjucerApplication::getApp().isPaidOrGPL(); | |||
| if (shouldDisplaySplashScreen() == var() || defaultSplashScreenAndReporting) | |||
| shouldDisplaySplashScreen() = defaultSplashScreenAndReporting; | |||
| if (shouldDisplaySplashScreen() == var() || defaultSplashScreen) | |||
| shouldDisplaySplashScreen() = defaultSplashScreen; | |||
| if (shouldReportAppUsage() == var() || defaultSplashScreenAndReporting) | |||
| shouldReportAppUsage() = defaultSplashScreenAndReporting; | |||
| if (ProjucerApplication::getApp().isPaidOrGPL()) | |||
| { | |||
| if (shouldReportAppUsage() == var()) | |||
| shouldReportAppUsage() = ProjucerApplication::getApp().licenseController->getState().applicationUsageDataState | |||
| == LicenseState::ApplicationUsageData::enabled; | |||
| } | |||
| else | |||
| shouldReportAppUsage() = true; | |||
| } | |||
| if (splashScreenColour() == var()) | |||
| @@ -0,0 +1,167 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library. | |||
| Copyright (c) 2017 - ROLI Ltd. | |||
| JUCE is an open source library subject to commercial or open-source | |||
| licensing. | |||
| By using JUCE, you agree to the terms of both the JUCE 5 End-User License | |||
| Agreement and JUCE 5 Privacy Policy (both updated and effective as of the | |||
| 27th April 2017). | |||
| End User License Agreement: www.juce.com/juce-5-licence | |||
| Privacy Policy: www.juce.com/juce-5-privacy-policy | |||
| Or: You may also use this code under the terms of the GPL v3 (see | |||
| www.gnu.org/licenses). | |||
| JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||
| EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||
| DISCLAIMED. | |||
| ============================================================================== | |||
| */ | |||
| #pragma once | |||
| class ApplicationUsageDataWindowComponent : public Component, | |||
| private Button::Listener | |||
| { | |||
| public: | |||
| ApplicationUsageDataWindowComponent (bool showCheckbox) | |||
| { | |||
| addAndMakeVisible (headerLabel); | |||
| headerLabel.setText ("Application Usage Analytics", dontSendNotification); | |||
| headerLabel.setFont (Font (20.0f, Font::FontStyleFlags::bold)); | |||
| headerLabel.setJustificationType (Justification::centred); | |||
| auto textToShow = String ("We use analytics services to understand how developers use our software in order for JUCE to improve its software and services. "); | |||
| if (! showCheckbox) | |||
| textToShow += String (" Analytics can be disabled with an Indie or Pro license. "); | |||
| textToShow += String ("For more information, please read the JUCE EULA and Privacy policy:"); | |||
| addAndMakeVisible (bodyLabel); | |||
| bodyLabel.setText (textToShow, dontSendNotification); | |||
| bodyLabel.setFont (Font (14.0f)); | |||
| bodyLabel.setJustificationType (Justification::centredLeft); | |||
| addAndMakeVisible (juceEULALink); | |||
| juceEULALink.setButtonText ("JUCE EULA"); | |||
| juceEULALink.setFont (Font (14.0f), false); | |||
| juceEULALink.setURL (URL ("https://juce.com/juce-5-license")); | |||
| addAndMakeVisible (privacyPolicyLink); | |||
| privacyPolicyLink.setButtonText ("Privacy Policy"); | |||
| privacyPolicyLink.setFont (Font (14.0f), false); | |||
| privacyPolicyLink.setURL (URL ("https://juce.com/privacy-policy")); | |||
| addAndMakeVisible (okButton); | |||
| okButton.setButtonText ("OK"); | |||
| okButton.addListener (this); | |||
| if (showCheckbox) | |||
| { | |||
| addAndMakeVisible (shareApplicationUsageDataToggle = new ToggleButton()); | |||
| shareApplicationUsageDataToggle->setToggleState (true, dontSendNotification); | |||
| addAndMakeVisible(shareApplicationUsageDataLabel = new Label ({}, "Help JUCE to improve its software and services by sharing my application usage data")); | |||
| shareApplicationUsageDataLabel->setFont (Font (14.0f)); | |||
| shareApplicationUsageDataLabel->setMinimumHorizontalScale (1.0f); | |||
| } | |||
| else | |||
| { | |||
| addAndMakeVisible (upgradeLicenseButton = new TextButton ("Upgrade License")); | |||
| upgradeLicenseButton->addListener (this); | |||
| upgradeLicenseButton->setColour (TextButton::buttonColourId, findColour (secondaryButtonBackgroundColourId)); | |||
| } | |||
| } | |||
| ~ApplicationUsageDataWindowComponent() | |||
| { | |||
| if (LicenseController* controller = ProjucerApplication::getApp().licenseController) | |||
| { | |||
| auto newApplicationUsageDataState = LicenseState::ApplicationUsageData::enabled; | |||
| if (shareApplicationUsageDataToggle != nullptr && ! shareApplicationUsageDataToggle->getToggleState()) | |||
| newApplicationUsageDataState = LicenseState::ApplicationUsageData::disabled; | |||
| controller->setApplicationUsageDataState (newApplicationUsageDataState); | |||
| } | |||
| } | |||
| void resized() override | |||
| { | |||
| auto bounds = getLocalBounds().reduced (20); | |||
| headerLabel.setBounds (bounds.removeFromTop (40)); | |||
| bodyLabel.setBounds (bounds.removeFromTop (75)); | |||
| bounds.removeFromTop (10); | |||
| auto linkBounds = bounds.removeFromTop (20); | |||
| juceEULALink.setBounds (linkBounds.removeFromLeft (linkBounds.getWidth() / 2).reduced (2)); | |||
| privacyPolicyLink.setBounds (linkBounds.reduced (2)); | |||
| if (shareApplicationUsageDataToggle != nullptr) | |||
| { | |||
| bounds.removeFromTop (10); | |||
| auto toggleBounds = bounds.removeFromTop (40); | |||
| shareApplicationUsageDataToggle->setBounds (toggleBounds.removeFromLeft (40).reduced (5)); | |||
| shareApplicationUsageDataLabel->setBounds (toggleBounds); | |||
| } | |||
| bounds.removeFromTop (10); | |||
| auto buttonW = 125; | |||
| auto buttonH = 40; | |||
| if (upgradeLicenseButton != nullptr) | |||
| { | |||
| auto left = bounds.removeFromLeft (bounds.getWidth() / 2); | |||
| upgradeLicenseButton->setSize (buttonW, buttonH); | |||
| upgradeLicenseButton->setCentrePosition (left.getCentreX(), left.getCentreY()); | |||
| } | |||
| okButton.setSize (buttonW, buttonH); | |||
| okButton.setCentrePosition (bounds.getCentreX(), bounds.getCentreY()); | |||
| } | |||
| void paint (Graphics& g) override | |||
| { | |||
| g.fillAll (findColour (backgroundColourId)); | |||
| } | |||
| private: | |||
| Label headerLabel, bodyLabel; | |||
| HyperlinkButton juceEULALink, privacyPolicyLink; | |||
| ScopedPointer<Label> shareApplicationUsageDataLabel; | |||
| ScopedPointer<ToggleButton> shareApplicationUsageDataToggle; | |||
| TextButton okButton; | |||
| ScopedPointer<TextButton> upgradeLicenseButton; | |||
| void buttonClicked (Button* b) override | |||
| { | |||
| if (b == &okButton) | |||
| { | |||
| ProjucerApplication::getApp().dismissApplicationUsageDataAgreementPopup(); | |||
| } | |||
| else if (b == upgradeLicenseButton) | |||
| { | |||
| if (LicenseController* controller = ProjucerApplication::getApp().licenseController) | |||
| controller->chooseNewLicense(); | |||
| } | |||
| } | |||
| void lookAndFeelChanged() override | |||
| { | |||
| if (upgradeLicenseButton != nullptr) | |||
| upgradeLicenseButton->setColour (TextButton::buttonColourId, findColour (secondaryButtonBackgroundColourId)); | |||
| } | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ApplicationUsageDataWindowComponent) | |||
| }; | |||
| @@ -47,7 +47,9 @@ struct FloatingToolWindow : public DialogWindow | |||
| setResizeLimits (minW, minH, maxW, maxH); | |||
| setContentOwned (content, false); | |||
| const String windowState (getGlobalProperties().getValue (windowPosProperty)); | |||
| String windowState; | |||
| if (windowPosProperty.isNotEmpty()) | |||
| windowState = getGlobalProperties().getValue (windowPosProperty); | |||
| if (windowState.isNotEmpty()) | |||
| restoreWindowStateFromString (windowState); | |||
| @@ -60,7 +62,8 @@ struct FloatingToolWindow : public DialogWindow | |||
| ~FloatingToolWindow() | |||
| { | |||
| getGlobalProperties().setValue (windowPosProperty, getWindowStateAsString()); | |||
| if (windowPosProperty.isNotEmpty()) | |||
| getGlobalProperties().setValue (windowPosProperty, getWindowStateAsString()); | |||
| } | |||
| void closeButtonPressed() override | |||