VST Plugin Still Not Getting Keystrokes

Discuss issues relating to audio plugins

VST Plugin Still Not Getting Keystrokes

Postby JuceProspector » Wed Mar 16, 2011 10:08 pm

This is an old but apparently still unsolved problem. In certain VST Hosts -- e.g. Cubase on Windows -- Juce labels and text editors do not receive keystrokes because the keystrokes are intercepted by the host sequencer. With some other dev toolkits -- e.g. VSTGUI -- this is not a problem. This implies that there is a solution that could be incorporated in Juce. This has been discussed in various threads in this forum for a number of years but apparently the problem persists. What is the status?
JuceProspector
JUCE Geek
 
Posts: 47
Joined: Mon Sep 20, 2010 10:09 pm

Re: VST Plugin Still Not Getting Keystrokes

Postby red_muze » Tue Mar 22, 2011 8:06 am

there was some kind of solution that was mentioned on the closed thread, but i am not sure if it works or not, that had to do with adding the Cubase key strokes to the vst wrapper. did anyone find a defect with this solution?
User avatar
red_muze
JUCE Obsessive
 
Posts: 97
Joined: Sat May 31, 2008 9:20 pm

Re: VST Plugin Still Not Getting Keystrokes

Postby JuceProspector » Wed Mar 23, 2011 7:43 am

The Cubase keywords are easily changed (added to or deleted) by the Cubase user so adding a list in the VST Wrapper would not be a very robust solution. I believe the keyboard focus issue needs to be resolved at the OS level. It already works on Mac OSX and VSTGUI is able to capture focus on Windows so there must be a solution.
JuceProspector
JUCE Geek
 
Posts: 47
Joined: Mon Sep 20, 2010 10:09 pm

Re: VST Plugin Still Not Getting Keystrokes

Postby Jakob » Thu Mar 31, 2011 2:02 pm

Yeah, this kept us busy for several work days to solve. This is the solution we came up with, do not know if this is the optimal solution, but it works for us. Also thanks a lot for all the posts in viewtopic.php?f=8&t=1662&start=30

Some extra code for Sonar, as Sonar passes keystrokes to the plugins.

First of all, in your <AudioProcessorEditor>, we added this:

Code: Select all
  // Request keyboard focus here, so that text fields do not get them automatically.
  setWantsKeyboardFocus(true);


Our <ModalTextEditor.h>:

Code: Select all
#if _WIN32
class ModalTextEditor: public juce::TextEditor, public juce::TextEditorListener
{

public:
   explicit ModalTextEditor();

   virtual ~ModalTextEditor();

public:
   void setTextColour
   ( const juce::Colour& colour );

   void setFocusedTextColour
   ( const juce::Colour& colour );
   
   virtual void focusGained
   ( juce::Component::FocusChangeType cause );

protected:
   void updateTextColour();
   
   virtual void focusLost
   ( juce::Component::FocusChangeType cause );

   //-- TextEditorListener
   void textEditorTextChanged
   ( TextEditor& editor ) { };

   void textEditorReturnKeyPressed
   ( TextEditor& editor );
   
   void textEditorEscapeKeyPressed
   ( TextEditor& editor );
   
   void textEditorFocusLost
   ( TextEditor& editor ) { };

private:
   juce::Colour m_textColour;
   juce::Colour m_focusedTextColour;
   juce::Component* m_oldParent;
   juce::Rectangle<int> m_oldBounds;

   bool m_isSonar;

   juce::String m_textBeforeEdit;
};

//-----------------------------------------------------------------------------------------
#else

class ModalTextEditor: public juce::TextEditor, public juce::TextEditorListener
{
public:
   ModalTextEditor();
   
   virtual ~ModalTextEditor();

public:
   void setTextColour
   ( const juce::Colour& colour ) { };
   
   void setFocusedTextColour
   ( const juce::Colour& colour ) { };

protected:
   void mouseDown
   ( const juce::MouseEvent& e );

   //-- TextEditorListener-Methoden
   void textEditorTextChanged
   ( juce::TextEditor& editor ) { };
   
   void textEditorReturnKeyPressed
   ( juce::TextEditor& editor );

   void textEditorEscapeKeyPressed
   ( juce::TextEditor& editor );
   
   void textEditorFocusLost
   ( juce::TextEditor& editor ) { };

private:
   juce::String m_textBeforeEdit;
};

#endif


Our <ModalTextEditor.cpp>:

Code: Select all
#if _WIN32
//==============================================================================
// Windows
//==============================================================================
ModalTextEditor::ModalTextEditor()
: juce::TextEditor("ModalTextEditor")
, m_oldParent(0)
, m_isSonar(false)
, m_textBeforeEdit("")
{
   setPopupMenuEnabled(false);
   setOpaque(true);
   addListener(this);

   // Set <m_isSonar>.
   const juce::String hostPath(juce::File::getSpecialLocation(juce::File::hostApplicationPath).getFullPathName());
   const juce::String hostFilename(juce::File(hostPath).getFileName());
   m_isSonar = hostFilename.containsIgnoreCase("SONAR");
};

//------------------------------------------------------------------------------
ModalTextEditor::~ModalTextEditor()
{
};

//------------------------------------------------------------------------------
void ModalTextEditor::focusGained
( juce::Component::FocusChangeType cause )
{
   if(m_isSonar)
   {
      juce::TextEditor::focusGained(cause);
   }
   else
   {
      if(!isOnDesktop())
      {
         m_oldBounds = getBounds();
         m_oldParent = getParentComponent();
         m_textBeforeEdit = getText();
         addToDesktop(juce::ComponentPeer::windowIsTemporary);
         updateTextColour();
         grabKeyboardFocus();
      }
   
      repaint();
   }
};

//------------------------------------------------------------------------------
void ModalTextEditor::focusLost
( juce::Component::FocusChangeType cause )
{
   if(!m_isSonar)
   {
      if(isOnDesktop() && m_oldParent != 0)
      {
         m_oldParent->addChildComponent(this);
         updateTextColour();
         setBounds(m_oldBounds);
         setHighlightedRegion(juce::Range<int>(0, 0));
      }
      
      repaint();
   }

   if(isCurrentlyModal())
   {
      exitModalState(0);
   }

   juce::TextEditor::focusLost(cause);
};

//------------------------------------------------------------------------------
void ModalTextEditor::textEditorReturnKeyPressed
( juce::TextEditor& editor )
{
   focusLost(focusChangedDirectly);
   moveKeyboardFocusToSibling(true);
   repaint();
};

//------------------------------------------------------------------------------
void ModalTextEditor::textEditorEscapeKeyPressed
( juce::TextEditor& editor )
{
   editor.setText(m_textBeforeEdit);

   focusLost(focusChangedDirectly);
   moveKeyboardFocusToSibling(true);
   repaint();
};

#else
//==============================================================================
// MAC
//==============================================================================
ModalTextEditor::ModalTextEditor()
: juce::TextEditor("ModalTextEditor")
, m_textBeforeEdit("")
{
   addListener(this);
};
   
//------------------------------------------------------------------------------
ModalTextEditor::~ModalTextEditor()
{
};
   
//------------------------------------------------------------------------------
void ModalTextEditor::mouseDown
( const juce::MouseEvent& e )
{
   juce::TextEditor::mouseDown(e);
   m_textBeforeEdit = getText();
   grabKeyboardFocus();
};
   
//------------------------------------------------------------------------------
void ModalTextEditor::textEditorReturnKeyPressed
( juce::TextEditor& editor )
{
   moveKeyboardFocusToSibling(true);
};
   
//------------------------------------------------------------------------------
void ModalTextEditor::textEditorEscapeKeyPressed
( juce::TextEditor& editor )
{
   moveKeyboardFocusToSibling(true);
   editor.setText(m_textBeforeEdit);
};
   
//------------------------------------------------------------------------------
#endif
User avatar
Jakob
JUCE Geek
 
Posts: 28
Joined: Mon Jun 14, 2010 6:45 pm

Re: VST Plugin Still Not Getting Keystrokes

Postby JuceProspector » Fri Apr 01, 2011 8:41 pm

Thanks so much for this. I will test it ASAP. I'm hoping that if this approach works then Jules will include it in the main release. There are a number of classes that either inherit from or aggregate TextEditor -- e.g. Label and Slider via Label -- so it becomes kind of a mess to reintegrate these kind of changes on every new Juce release.
JuceProspector
JUCE Geek
 
Posts: 47
Joined: Mon Sep 20, 2010 10:09 pm

Re: VST Plugin Still Not Getting Keystrokes

Postby steffen » Fri Apr 01, 2011 11:46 pm

to avoid subclassing, we placed all the stuff required for keyboard focus in a combined MouseListener/TextEditorListener.

When creating the PluginEditor, the host type is checked, and the listeners are added to all TextEditors in the component hierarchy. What I like about that approach is that you don't change the functionality if the same components are used in a standalone application. What I don't like is that you need to manually add it for all components created *after* initialization of the PluginEditor (unless they are in a modal dialog which seems to work fine).

Here's our implementation of such a listener. There's an ugly work around because textEditorFocusLost was called twice (at least in ableton live on win) and for some reason the editor couldn't be removed from the desktop in the first call.


Code: Select all
    ///////////////////////////////////////////////////////////////////////////
    class KeyboardFocusWorkaroundListener : public MouseListener,
                                            public TextEditorListener
    {
    public:

        KeyboardFocusWorkaroundListener(TextEditor* pTextEditor)
            : m_pTextEditor(pTextEditor),
              m_bRemoveWhenLosingFocus(false),
              m_pOriginalParent(0),
              m_bIsOnDesktop(false)
        {

        }

        void mouseDown(const MouseEvent& e)
        {   
            addEditorToDesktop();
        }

        void mouseExit(const MouseEvent e)
        {

        }

        virtual void textEditorTextChanged (TextEditor& editor)       { }
        virtual void textEditorReturnKeyPressed (TextEditor& editor)
        {
            removeEditorFromDesktop();
        }
        virtual void textEditorEscapeKeyPressed (TextEditor& editor)
        {
            removeEditorFromDesktop();
        }
        virtual void textEditorFocusLost (TextEditor& editor)
        {
            if (m_bRemoveWhenLosingFocus)
            {
                removeEditorFromDesktop();
            }
            else
            {
                m_bRemoveWhenLosingFocus = true;
            }
        }

        juce_UseDebuggingNewOperator

    protected:

        void addEditorToDesktop()
        {
            if (m_bIsOnDesktop) return;

            m_originalBounds = m_pTextEditor->getBounds();
            m_pOriginalParent = m_pTextEditor->getParentComponent();
           
            m_bRemoveWhenLosingFocus = false;

            m_pTextEditor->addToDesktop(ComponentPeer::windowIsTemporary);
            m_pTextEditor->grabKeyboardFocus();

            m_bIsOnDesktop = true;
        }

        void removeEditorFromDesktop()
        {
            if (!m_bIsOnDesktop) return;

            m_pTextEditor->removeFromDesktop();

            if (m_pOriginalParent != 0)
            {
                m_pOriginalParent->addChildComponent(m_pTextEditor);
            }

            m_pTextEditor->setBounds(m_originalBounds);

            m_bIsOnDesktop = false;
        }

    private:

        bool m_bIsOnDesktop;
        bool m_bRemoveWhenLosingFocus;

        Rectangle<int> m_originalBounds;
        Component* m_pOriginalParent;

        TextEditor* m_pTextEditor;

    };


If you're worried about subclassing, it might be worth going this way (but Jakob's is probably better tested, we didn't test much with Sonar). If you come up with something that combines both approaches, I'd be happy to test it in ableton live on win/osx.
steffen
JUCE UberWeenie
 
Posts: 140
Joined: Tue May 04, 2010 11:52 am

Re: VST Plugin Still Not Getting Keystrokes

Postby RiphRaph » Tue Jun 21, 2011 11:57 am

Hi all,
Based on the code zamrate wrote few years ago (see an older thread about this problem), I wrote a class called MySliderLabel that I use to edit the value of my slider.
TheText Editor is actually a modal window so it REALLY gets the focus on the keyboard and loses it as soon as the user presses enter, escape or clicks elsewhere.
edit() is called from the ShowTextBox function of my slider.
Hope this will help some of you.
Cheers
Raph

(with a little update of the code)

MySliderLabel.h:
Code: Select all

#ifndef __MYSLIDERLABEL_HEADER__
#define __MYSLIDERLABEL_HEADER__

#include "MySlider.h"
class MySlider;

class MySliderTextEditor : public TextEditor
{
public:

// if a mouse down event happens, exit the modal text editor window
   bool canModalEventBeSentToComponent (const Component* comp)
   {
      if (comp->isMouseButtonDownAnywhere())
      {
         exitModalState(0);
      }

      return false;
   }
};



class MySliderLabel : public Label
{
public:
   MySliderLabel();
   ~MySliderLabel();

   void setText(const String &text)
   {
      mText = text;
      repaint();
   }

   const String& getText(){return mText;}
   void edit();
   bool isBeingEdited(){return mbLabelIsEdited;};

 
private:   
   String      mText;
   MySlider*          mpSlider;
   bool         mbLabelIsEdited;

    void  textEditorReturnKeyPressed (TextEditor &editor)
   {
      editor.exitModalState(0);
   }

    void  textEditorEscapeKeyPressed (TextEditor &editor)
   {
      editor.exitModalState(0);
   }

    void  textEditorFocusLost (TextEditor &editor)
   {
      editor.exitModalState(0);
   }

   void mouseUp (const MouseEvent& e);

};

#endif




MySliderLabel.cpp:
Code: Select all
// MySliderLabel gets the focus on the sliderLabel

#include "MySliderLabel.h"

MySliderLabel :: MySliderLabel(Slider* slider)
{
  setRepaintsOnMouseActivity(true);   
   mpSlider = (MySlider*) slider;
   mpSlider->setSliderLabelPtr(this);

  mbLabelIsEdited = false;
}

MySliderLabel :: ~MySliderLabel()
{
}

// Caledl from MySlider::ShowTextEditor: pops up a modal text editor
void MySliderLabel :: edit()
{
   mbLabelIsEdited = true;

   MySliderTextEditor* ed = new MySliderTextEditor();

   ed->setColour(TextEditor::backgroundColourId,Colours::white);
   ed->setColour(TextEditor::textColourId,Colours::black);

   ed->setColour(TextEditor::highlightColourId,Colours::black);
   ed->setColour(TextEditor::highlightedTextColourId,Colours::white);

   ed->setBounds(0, 0, getWidth(), getHeight());
   ed->setFont(Font ("Futura", 11, Font::bold));

   ed->setText(getText(),false);
   Range<int>  range(0, getText().length());
   ed->setHighlightedRegion(range);

   addAndMakeVisible(ed);
   ed->addListener(this);

   ed->runModalLoop();

   setText(ed->getText());

   deleteAndZero(ed);

   mbLabelIsEdited = false;
}

void MySliderLabel :: mouseUp (const MouseEvent& e)
{
   if (e.mouseWasClicked()
     && contains (e.getPosition())
     && ! e.mods.isPopupMenu())
   {
      mpSlider->showTextBox();
   }
}



MyLabel.cpp file:
Code: Select all
#include "MyLookAndFeel.h"
#include "MySlider.h"

//==============================================================================
MySlider:: MySlider(const String& componentName)
               : Slider        (componentName)
{

   mpSliderLabel = NULL;
   setLookAndFeel (MyLookAndFeel::getInstance());
   setBufferedToImage(true);

}
//==============================================================================
MySlider:: ~MySlider()
{
}

//==============================================================================
void MySlider::showTextBox()
{
    if (mpSliderLabel)
      {
      const String suffix = getTextValueSuffix();
      mpSliderLabel->setText(getTextFromValue(getValue()).removeCharacters(suffix));
      mpSliderLabel->edit();
      setValue(getValueFromText(mpSliderLabel->getText()));    
   }
}


MySlider.h:
Code: Select all

#ifndef __MY_SLIDER_HEADER__
#define __MY_SLIDER_HEADER__

#include "../JuceLibraryCode/JuceHeader.h"
#include "MySliderLabel.h"

class MySliderLabel;
class MySlider:   public Slider
{
public:
   MySlider(const String& componentName);
   ~MySlider();

   void showTextBox();

   void setSliderLabelPtr(MySliderLabel* ptr) {mpSliderLabel = ptr;};

private:
   MySliderLabel* mpSliderLabel;
};

#endif


And filnally the lookAndFeel file:
MyLookAndFeel.h:
Code: Select all
#ifndef _MY_LOOKANDFEEL_HEADER_
#define _MY_LOOKANDFEEL_HEADER_

#include "../JuceLibraryCode/JuceHeader.h"
// ==============================================================================

class MyLookAndFeel: public LookAndFeel
{
public:
   static MyLookAndFeel* getInstance();

private:
   Label* createSliderTextBox (Slider& slider);
};

#endif


MyLookAndFeel.hcpp
Code: Select all
#include "MyLookAndFeel.h"
#include "MySliderLabel.h"

//----------------------------------------------------------------------//
MyLookAndFeel* MyLookAndFeel::getInstance()
{
   static  MyLookAndFeel myLookAndFeel;
   return &myLookAndFeel;
}

//
//==============================================================================

Label* MyLookAndFeel::createSliderTextBox(Slider& slider)
{
   MySliderLabel* l = new MySliderLabel(&slider);

    l->setJustificationType (Justification::centred);

    l->setColour (Label::textColourId, slider.findColour (Slider::textBoxTextColourId));

    l->setColour (Label::backgroundColourId,
                  (slider.getSliderStyle() == Slider::LinearBar) ? Colours::transparentBlack
                                                                 : slider.findColour (Slider::textBoxBackgroundColourId));
    l->setColour (Label::outlineColourId, slider.findColour (Slider::textBoxOutlineColourId));

    l->setColour (TextEditor::textColourId, slider.findColour (Slider::textBoxTextColourId));

    l->setColour (TextEditor::backgroundColourId,
                  slider.findColour (Slider::textBoxBackgroundColourId)
                        .withAlpha (slider.getSliderStyle() == Slider::LinearBar ? 0.7f : 1.0f));

    l->setColour (TextEditor::outlineColourId, slider.findColour (Slider::textBoxOutlineColourId));

    return l;
}
Last edited by RiphRaph on Tue Sep 27, 2011 5:30 pm, edited 1 time in total.
RiphRaph
JUCE Geek
 
Posts: 37
Joined: Tue Oct 12, 2010 10:11 am

Re: VST Plugin Still Not Getting Keystrokes

Postby 200gaga » Thu Aug 18, 2011 4:29 pm

I can't find ShowTextBox in Label class.Did you write it on your own?
200gaga
JUCE Weenie
 
Posts: 2
Joined: Wed Aug 17, 2011 3:41 pm

Re: VST Plugin Still Not Getting Keystrokes

Postby zamrate » Sat Sep 03, 2011 7:11 am

It's rather unbelievable that this question comes up ever again, when I've posted a solution, which worked, but for mysterious reasons never made its way into JUCE. Link: viewtopic.php?f=8&t=1662&hilit=keystrokes&start=60 Check out the bottom of page 4 (last code I posted).
User avatar
zamrate
JUCE UberWeenie
 
Posts: 1081
Joined: Mon Sep 24, 2007 5:33 pm

Re: VST Plugin Still Not Getting Keystrokes

Postby Shlomi » Sun Sep 04, 2011 8:28 pm

Hi Zamrate.

I really like your solution cause it's not intrusive like other solutions suggested here (like adding components to the desktop upon focus gain).
Though I can't get the control modifier working in your solution, so I can't use it for now.

What I did was to add the entire component of my application to the desktop on focus gain/ mouse enter.
User avatar
Shlomi
JUCE UberWeenie
 
Posts: 395
Joined: Tue Dec 28, 2010 2:06 pm

Re: VST Plugin Still Not Getting Keystrokes

Postby steffen » Tue Sep 06, 2011 4:55 pm

zamrate wrote:It's rather unbelievable that this question comes up ever again, when I've posted a solution, which worked, but for mysterious reasons never made its way into JUCE. Link: viewtopic.php?f=8&t=1662&hilit=keystrokes&start=60 Check out the bottom of page 4 (last code I posted).


I just tried your patch, and keyboard input indeed works perfectly in Live 8.2.1, but there is still trouble in Cubase 6 (32bit).

Many keys work well (numbers, letters, space, backspace, cursors, shift) but others don't: commas and the period key and the whole number block (which is weird because it looks like its keys are explicitly mapped in your code).

I'd like to get rid of the focus/desktop workarounds, but being able to enter decimal separators is an absolute must for those text fields.

Any ideas wants going wrong here? Maybe it makes a difference that I am using a German keyboard layout?
steffen
JUCE UberWeenie
 
Posts: 140
Joined: Tue May 04, 2010 11:52 am

Re: VST Plugin Still Not Getting Keystrokes

Postby zamrate » Mon Sep 12, 2011 8:19 pm

Dunno, isn't Cubase maybe just blocking these keys?
User avatar
zamrate
JUCE UberWeenie
 
Posts: 1081
Joined: Mon Sep 24, 2007 5:33 pm

Re: VST Plugin Still Not Getting Keystrokes

Postby steffen » Tue Sep 13, 2011 12:51 pm

I just stepped into it, and there seem to be two differences between Cubase 6 and Live 8 in the calls to your convertVstKeyInputToKeyCodeAndTextCharacter

- For the keys on the keypad, in Live the 'index' is != 0 so they are treated as ascii. In Cubase 6 however, 'index' is 0 and 'value' equals of the VKEY_ constants instead - no matter if num-lock is active or not. Because 'textCharacter' is never set in that case, the TextEditor won't treat it as text input later. A possible workaround (if you don't need cursor movement with the keypad) seems to be to additionally set textCharacter to the character that corresponds to the key.

- the situation for the regular +-., keys is worse. In Cubase 6, you do get an effEditKeyDown event, bot both 'index' and 'value' are 0. So there doesn't seem to be chance at all at distinguishing these keys.
steffen
JUCE UberWeenie
 
Posts: 140
Joined: Tue May 04, 2010 11:52 am

Re: VST Plugin Still Not Getting Keystrokes

Postby RiphRaph » Wed Sep 28, 2011 1:11 pm

HI all,

200gaga:
I can't find ShowTextBox in Label class.Did you write it on your own?

ShowTextBox is in the Slider class and is called to create and make visible the textbox.

Shlomi :
Though I can't get the control modifier working in your solution, so I can't use it for now.

I did a little improvement of the zamrate patch in juce_VST_wrapper.cpp to make modifier keys work in Cubase. Check it out:


Code: Select all
void convertVstKeyInputToKeyCodeAndTextCharacter(int opCode, int value, int index, int &keyCode, int &textCharacter, int &modifierKey)
{
   keyCode=0;
   textCharacter=0;
   modifierKey = 0;


   if (opCode==effEditKeyDown)
   {

      if (value == VKEY_CONTROL || value == VKEY_SHIFT || value == VKEY_ALT)
      {
         modifierKey = value;
         return;
      }

       for (int i=0; i<sizeof(vstVirtualKeyCodeConversionTable)/(2*sizeof(int));i++)
       {
            if (value==vstVirtualKeyCodeConversionTable[i*2])
            {
               keyCode=vstVirtualKeyCodeConversionTable[i*2+1];
               break;
            }
       }       
     
      textCharacter=index; // ascii
   }
}


and in the dispatcher:

Code: Select all
     if (opCode == effEditKeyDown || opCode == effEditKeyUp)
      {
         
#if JUCE_WIN32
         if (editorComp!=0)
         {
            int keyCode, textCharacter;
            int modifierKey;
            convertVstKeyInputToKeyCodeAndTextCharacter(opCode, value, index, keyCode, textCharacter, modifierKey);

            ComponentPeer *peer=editorComp->getPeer();
            if (peer!=0)
         {
            if (keyCode!=0 || textCharacter!=0)
            {   
               return peer->handleKeyPress (keyCode, textCharacter);
            }

            if (modifierKey)
            {
               int keyMods = 0;
   
               if (modifierKey == VKEY_CONTROL)   keyMods |= ModifierKeys::ctrlModifier;
               if (modifierKey == VKEY_SHIFT)      keyMods |= ModifierKeys::shiftModifier;
               if (modifierKey == VKEY_ALT)      keyMods |= ModifierKeys::altModifier;

               ModifierKeys::getCurrentModifiers().withFlags (keyMods);
            }
         }
            return 0;
         }
#endif



I use both methods in my code, the first one is just text boxes, whereas I use the second one for overall keyboard shortcuts, and I'm happy with it.
RiphRaph
JUCE Geek
 
Posts: 37
Joined: Tue Oct 12, 2010 10:11 am

Re: VST Plugin Still Not Getting Keystrokes

Postby andrewsimper » Sat Jan 14, 2012 3:48 am

The solution posted by RiphRaph is the best way to solve this. I have a slightly more basic version which is called a PopupTextEditor, which I think really should be integrated into the main TextEditor code since this comes up over and over again. It would be much more preferable for plugins that they just set a property on the slider text editor saying it should popup in a new window, then vanish again once enter / escape / lost focus. You can even specialise what is below to pull the formatting directly from the label / text editor of the slider.

Code: Select all
   class PopupTextEditor;

   class PopupTextEditorListener
   {
   public:
      //==============================================================================
      juce_UseDebuggingNewOperator

      virtual ~PopupTextEditorListener () {};
      virtual void textEditAccepted (PopupTextEditor* editor, const juce::String& text) = 0;
      virtual void textEditRejected (PopupTextEditor* editor) = 0;
   };

   class PopupTextEditor
      : public TextEditorListener
        , public ComponentListener
   {
   public:
      //==============================================================================
      juce_UseDebuggingNewOperator

        class TextEditorModal : public TextEditor
        {
        public:
            TextEditorModal (const juce::String name) : TextEditor (name) {};
            virtual void inputAttemptWhenModal ()
            {
                returnPressed();
                exitModalState (0);
            }
        };
       
      PopupTextEditor (const juce::String& name, PopupTextEditorListener* listener);
      virtual ~PopupTextEditor ();

      const juce::String& getName () const;
      void setColour (const int colourId, const Colour& colour);
      void setFont (const Font& font);
      void showOverWithText (Component* anchor, juce::String& text);

      virtual void textEditorTextChanged (TextEditor& editor);
      virtual void textEditorReturnKeyPressed (TextEditor& editor);
      virtual void textEditorEscapeKeyPressed (TextEditor& editor);
      virtual void textEditorFocusLost (TextEditor& editor);

   protected:
      juce::String name;
        juce::String text;
      PopupTextEditorListener* listener;
        TextEditorModal* texteditor;
   };


PopupTextEditor::PopupTextEditor (const String& name_, PopupTextEditorListener* listener_)
: name (name_)
, listener (listener_)
{
   jassert (listener);
   texteditor = new TextEditorModal (name_);
   texteditor->addListener (this);
   jassert (texteditor);
}

PopupTextEditor::~PopupTextEditor ()
{
   if (texteditor)
   {
      delete texteditor;
   }
}
const String& PopupTextEditor::getName () const
{
   return name;
}
void PopupTextEditor::setColour (const int colourId, const Colour& colour)
{
   texteditor->setColour (colourId, colour);
}
void PopupTextEditor::setFont (const Font& font)
{
   texteditor->setFont (font);
}
void PopupTextEditor::showOverWithText (Component* anchor, String& text)
{
    ModalComponentManager::Callback* userCallback = 0;
    ScopedPointer<ModalComponentManager::Callback> userCallbackDeleter (userCallback);

    Component::SafePointer<Component> prevFocused (Component::getCurrentlyFocusedComponent());
    Component::SafePointer<Component> prevTopLevel ((prevFocused != 0) ? prevFocused->getTopLevelComponent() : 0);
    texteditor->setWantsKeyboardFocus (true);
   Rectangle<int> sr (anchor->getBounds ());
   sr.setPosition (anchor->getScreenX(), anchor->getScreenY());
    int fontheight = texteditor->getFont().getHeight() + 4;
    if (sr.getHeight() > fontheight)
    {
        sr.translate (0, (sr.getHeight() - fontheight)/2);
        sr.setHeight (fontheight);
    }
   texteditor->setAlwaysOnTop (true);
   texteditor->setBounds (sr);
   texteditor->setText (text);
   texteditor->setHighlightedRegion (Range <int> (0, text.length ()));
   texteditor->setVisible (true);
    texteditor->grabKeyboardFocus();

    texteditor->addToDesktop (ComponentPeer::windowIsTemporary, 0);
   
   texteditor->addListener (this);
    texteditor->enterModalState (false);
    texteditor->grabKeyboardFocus ();

    const int result = texteditor->runModalLoop();

    {
        if (prevTopLevel != 0)
            prevTopLevel->toFront (true);

        if (prevFocused != 0)
            prevFocused->grabKeyboardFocus();
    }
}
void PopupTextEditor::textEditorTextChanged (TextEditor& editor)
{
   // do nothing until the return or escape key is pressed
}
void PopupTextEditor::textEditorReturnKeyPressed (TextEditor& editor)
{
   jassert (listener);
   String text = editor.getText ();
   listener->textEditAccepted (this, text);
    texteditor->exitModalState(1);
}
void PopupTextEditor::textEditorEscapeKeyPressed (TextEditor& editor)
{
   jassert (listener);
   listener->textEditRejected (this);
    texteditor->exitModalState(0);
}
void PopupTextEditor::textEditorFocusLost (TextEditor& editor)
{
    texteditor->exitModalState(0);
}
www.cytomic.com
sound music software
User avatar
andrewsimper
JUCE UberWeenie
 
Posts: 158
Joined: Mon Nov 03, 2008 1:24 pm

Next

Return to Audio Plugins

Who is online

Users browsing this forum: No registered users and 3 guests