The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

302 lines
11KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2015 - ROLI Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. #ifndef PROJUCER_LOGINFORM_H_INCLUDED
  18. #define PROJUCER_LOGINFORM_H_INCLUDED
  19. class LoginForm : public Component,
  20. public ButtonListener,
  21. private TextEditor::Listener,
  22. private ProjucerLicences::LoginCallback
  23. {
  24. public:
  25. LoginForm()
  26. : cancelButton (TRANS("Cancel")),
  27. loginButton (TRANS("Login")),
  28. registerButton (TRANS("Register")),
  29. userIDEditor ("User ID text editor"),
  30. passwordEditor ("Password TextEditor", juce_wchar (0x2022)),
  31. userIDLabel ("User-ID Label", TRANS("Username")),
  32. passwordLabel ("Password Label", TRANS("Password")),
  33. errorLabel ("Error Label", String()),
  34. rememberLoginCheckbox (TRANS("Remember login")),
  35. forgotPasswordButton (TRANS("Forgotten your password?"),
  36. URL (getServerURL() + "reset_password?referer=projucer")),
  37. rememberLogin (true)
  38. {
  39. setLookAndFeel (&lookAndFeel);
  40. ScopedPointer<XmlElement> svg (XmlDocument::parse (BinaryData::projucer_login_bg_svg));
  41. backgroundImage = Drawable::createFromSVG (*svg);
  42. initialiseTextField (passwordEditor, passwordLabel);
  43. addAndMakeVisible (passwordEditor);
  44. initialiseTextField (userIDEditor, userIDLabel);
  45. addAndMakeVisible (userIDEditor);
  46. userIDEditor.setText (ProjucerLicences::getInstance()->getLoginName());
  47. initialiseLabel (errorLabel, Font::plain, ProjucerDialogLookAndFeel::getErrorTextColour());
  48. addChildComponent (errorLabel);
  49. addChildComponent (spinner);
  50. rememberLoginCheckbox.setColour (ToggleButton::textColourId, Colours::white);
  51. rememberLoginCheckbox.setColour (TextEditor::focusedOutlineColourId, Colours::transparentBlack);
  52. rememberLoginCheckbox.setToggleState (rememberLogin, dontSendNotification);
  53. addAndMakeVisible (rememberLoginCheckbox);
  54. rememberLoginCheckbox.addListener (this);
  55. forgotPasswordButton.setColour (HyperlinkButton::textColourId, Colours::white);
  56. forgotPasswordButton.setFont (lookAndFeel.getContaxProFont().withHeight (lookAndFeel.labelFontSize), false, Justification::topLeft);
  57. addAndMakeVisible (forgotPasswordButton);
  58. initialiseButton (loginButton, KeyPress::returnKey);
  59. addAndMakeVisible (loginButton);
  60. initialiseButton (registerButton);
  61. addAndMakeVisible (registerButton);
  62. initialiseButton (cancelButton, KeyPress::escapeKey);
  63. addAndMakeVisible (cancelButton);
  64. cancelButton.getProperties().set ("isSecondaryButton", true);
  65. centreWithSize (425, 685);
  66. }
  67. ~LoginForm()
  68. {
  69. ProjucerApplication::getApp().hideLoginForm();
  70. }
  71. //==============================================================================
  72. void paint (Graphics& g) override
  73. {
  74. g.fillAll (Colour (0xff4d4d4d));
  75. g.setColour (Colours::black);
  76. backgroundImage->drawWithin (g, getLocalBounds().toFloat(), RectanglePlacement::centred, 1.0f);
  77. }
  78. void resized() override
  79. {
  80. const int xMargin = 81;
  81. const int yMargin = 132;
  82. const int labelHeight = 24;
  83. const int textFieldHeight = 33;
  84. Rectangle<int> r = getLocalBounds().reduced (xMargin, yMargin);
  85. r.setWidth (r.getWidth() + 1);
  86. Point<int> labelOffset = Point<int> (-6, 4);
  87. userIDLabel.setBounds (r.removeFromTop (labelHeight) + labelOffset);
  88. userIDEditor.setBounds (r.removeFromTop (textFieldHeight));
  89. passwordLabel.setBounds (r.removeFromTop (labelHeight) + labelOffset);
  90. passwordEditor.setBounds (r.removeFromTop (textFieldHeight));
  91. r.removeFromTop (6);
  92. rememberLoginCheckbox.setBounds (r.removeFromTop (labelHeight) + Point<int> (-4, 0));
  93. r.removeFromTop (8);
  94. errorLabel.setBounds (r.removeFromTop (43).withTrimmedLeft (15));
  95. spinner.setBounds (errorLabel.getBounds().withSizeKeepingCentre (20, 20) + Point<int> (-7, -10));
  96. const int buttonHeight = 40;
  97. const int buttonMargin = 13;
  98. loginButton.setBounds (r.removeFromTop (buttonHeight));
  99. r.removeFromTop (buttonMargin);
  100. registerButton.setBounds (r.withHeight (buttonHeight).removeFromLeft ((r.getWidth() - buttonMargin) / 2));
  101. cancelButton.setBounds (r.withHeight (buttonHeight).removeFromRight ((r.getWidth() - buttonMargin) / 2));
  102. r.removeFromTop (45);
  103. forgotPasswordButton.setBounds (r.withHeight (labelHeight) + Point<int> (-2, 0));
  104. }
  105. private:
  106. //==============================================================================
  107. struct Spinner : public Component,
  108. private Timer
  109. {
  110. Spinner()
  111. {
  112. setInterceptsMouseClicks (false, false);
  113. }
  114. void paint (Graphics& g) override
  115. {
  116. getLookAndFeel().drawSpinningWaitAnimation (g, Colours::white, 0, 0, getWidth(), getHeight());
  117. startTimer (50);
  118. }
  119. void timerCallback() override
  120. {
  121. if (isVisible())
  122. repaint();
  123. else
  124. stopTimer();
  125. }
  126. };
  127. //==============================================================================
  128. void initialiseTextField (TextEditor& textField, Label& associatedLabel)
  129. {
  130. textField.setColour (TextEditor::focusedOutlineColourId, Colours::transparentWhite);
  131. textField.setColour (TextEditor::highlightColourId, ProjucerDialogLookAndFeel::getErrorTextColour());
  132. textField.setFont (lookAndFeel.getContaxProFont().withHeight (17));
  133. textField.addListener (this);
  134. associatedLabel.setColour (Label::textColourId, Colours::white);
  135. addAndMakeVisible (associatedLabel);
  136. }
  137. void initialiseButton (TextButton& button, const int associatedKeyPress = 0)
  138. {
  139. if (associatedKeyPress != 0)
  140. button.addShortcut (KeyPress (associatedKeyPress));
  141. button.addListener (this);
  142. }
  143. void initialiseLabel (Label& label, Font::FontStyleFlags fontFlags, Colour textColour)
  144. {
  145. label.setFont (Font (15.0f, fontFlags));
  146. label.setJustificationType (Justification::topLeft);
  147. label.setColour (Label::textColourId, textColour);
  148. }
  149. //==============================================================================
  150. void buttonClicked (Button* button) override
  151. {
  152. if (button == &cancelButton) cancelButtonClicked();
  153. if (button == &loginButton) loginButtonClicked();
  154. if (button == &registerButton) registerButtonClicked();
  155. if (button == &rememberLoginCheckbox) rememberLoginCheckboxClicked();
  156. }
  157. void cancelButtonClicked()
  158. {
  159. if (DialogWindow* parentDialog = findParentComponentOfClass<DialogWindow>())
  160. parentDialog->exitModalState (-1);
  161. }
  162. void loginButtonClicked()
  163. {
  164. loginName = userIDEditor.getText();
  165. password = passwordEditor.getText();
  166. if (! isValidEmail (loginName) || password.isEmpty())
  167. {
  168. handleInvalidLogin();
  169. return;
  170. }
  171. loginButton.setEnabled (false);
  172. cancelButton.setEnabled (false);
  173. registerButton.setEnabled (false);
  174. errorLabel.setVisible (false);
  175. spinner.setVisible (true);
  176. ProjucerLicences::getInstance()->login (loginName, password, rememberLogin, this);
  177. }
  178. void registerButtonClicked()
  179. {
  180. URL (getServerURL() + "projucer_trial").launchInDefaultBrowser();
  181. }
  182. void textEditorReturnKeyPressed (TextEditor&) override
  183. {
  184. loginButtonClicked();
  185. }
  186. void rememberLoginCheckboxClicked()
  187. {
  188. rememberLogin = rememberLoginCheckbox.getToggleState();
  189. }
  190. void handleInvalidLogin()
  191. {
  192. if (!isValidEmail (loginName))
  193. loginError (TRANS ("Please enter a valid e-mail address"), true);
  194. if (password.isEmpty())
  195. loginError (TRANS ("Please specify a valid password"), false);
  196. }
  197. bool isValidEmail (const String& email)
  198. {
  199. return email.isNotEmpty();
  200. }
  201. void loginError (const String& errorMessage, bool hiliteUserID) override
  202. {
  203. spinner.setVisible (false);
  204. errorLabel.setText (errorMessage, dontSendNotification);
  205. errorLabel.setVisible (true);
  206. TextEditor& field = hiliteUserID ? userIDEditor : passwordEditor;
  207. field.setColour (TextEditor::focusedOutlineColourId, Colour (0x84F08080));
  208. field.toFront (true);
  209. loginButton.setEnabled (true);
  210. cancelButton.setEnabled (true);
  211. registerButton.setEnabled (true);
  212. ProjucerApplication::getApp().updateAllBuildTabs();
  213. }
  214. void loginSuccess (const String& username, const String& apiKey) override
  215. {
  216. ignoreUnused (username, apiKey);
  217. spinner.setVisible (false);
  218. if (DialogWindow* parentDialog = findParentComponentOfClass<DialogWindow>())
  219. {
  220. parentDialog->exitModalState (0);
  221. ProjucerApplication::getApp().updateAllBuildTabs();
  222. }
  223. }
  224. TextButton cancelButton, loginButton, registerButton;
  225. TextEditor userIDEditor, passwordEditor;
  226. Label userIDLabel, passwordLabel, errorLabel;
  227. ToggleButton rememberLoginCheckbox;
  228. HyperlinkButton forgotPasswordButton;
  229. Spinner spinner;
  230. String loginName, password;
  231. bool rememberLogin;
  232. ScopedPointer<Drawable> backgroundImage;
  233. ProjucerDialogLookAndFeel lookAndFeel;
  234. static String getServerURL() { return "https://my.roli.com/"; }
  235. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LoginForm)
  236. };
  237. #endif // PROJUCER_LOGINFORM_H_INCLUDED