Browse Source

Update cabbage code

master
falkTX 10 years ago
parent
commit
63674b5446
50 changed files with 24092 additions and 19269 deletions
  1. +684
    -671
      ports/cabbage/source/BinaryData.cpp
  2. +26
    -26
      ports/cabbage/source/BinaryData.h
  3. +15
    -13
      ports/cabbage/source/CabbageCallOutBox.cpp
  4. +7
    -7
      ports/cabbage/source/CabbageCallOutBox.h
  5. +1706
    -1994
      ports/cabbage/source/CabbageCustomWidgets.h
  6. +1913
    -1751
      ports/cabbage/source/CabbageGUIClass.cpp
  7. +308
    -258
      ports/cabbage/source/CabbageGUIClass.h
  8. +1551
    -1446
      ports/cabbage/source/CabbageLookAndFeel.cpp
  9. +173
    -156
      ports/cabbage/source/CabbageLookAndFeel.h
  10. +42
    -42
      ports/cabbage/source/CabbageMainPanel.cpp
  11. +115
    -102
      ports/cabbage/source/CabbageMainPanel.h
  12. +84
    -70
      ports/cabbage/source/CabbageMessageSystem.h
  13. +66
    -61
      ports/cabbage/source/CabbagePropertiesDialog.cpp
  14. +525
    -475
      ports/cabbage/source/CabbagePropertiesDialog.h
  15. +902
    -808
      ports/cabbage/source/CabbageTable.cpp
  16. +146
    -138
      ports/cabbage/source/CabbageTable.h
  17. +599
    -626
      ports/cabbage/source/CabbageUtils.h
  18. +587
    -524
      ports/cabbage/source/ComponentLayoutEditor.cpp
  19. +111
    -108
      ports/cabbage/source/ComponentLayoutEditor.h
  20. +172
    -160
      ports/cabbage/source/DirectoryContentsComponent.cpp
  21. +188
    -172
      ports/cabbage/source/DirectoryContentsComponent.h
  22. +1201
    -382
      ports/cabbage/source/Editor/CodeEditor.cpp
  23. +386
    -55
      ports/cabbage/source/Editor/CodeEditor.h
  24. +868
    -653
      ports/cabbage/source/Editor/CodeWindow.cpp
  25. +206
    -502
      ports/cabbage/source/Editor/CodeWindow.h
  26. +1
    -1
      ports/cabbage/source/Editor/CommandManager.cpp
  27. +47
    -44
      ports/cabbage/source/Editor/CommandManager.h
  28. +205
    -168
      ports/cabbage/source/Editor/CsoundTokeniser.h
  29. +41
    -39
      ports/cabbage/source/Editor/KeyboardShortcuts.h
  30. +201
    -198
      ports/cabbage/source/Editor/PythonTokeniser.h
  31. +408
    -0
      ports/cabbage/source/Editor/SplitComponent.cpp
  32. +273
    -0
      ports/cabbage/source/Editor/SplitComponent.h
  33. +1915
    -1792
      ports/cabbage/source/Editor/opcodes.txt
  34. +2
    -0
      ports/cabbage/source/JuceHeader.h
  35. +2
    -2
      ports/cabbage/source/JucePluginCharacteristics.h
  36. +82
    -82
      ports/cabbage/source/Plugin/CabbageGenericAudioProcessorEditor.h
  37. +2965
    -2918
      ports/cabbage/source/Plugin/CabbagePluginEditor.cpp
  38. +197
    -148
      ports/cabbage/source/Plugin/CabbagePluginEditor.h
  39. +1573
    -1043
      ports/cabbage/source/Plugin/CabbagePluginProcessor.cpp
  40. +450
    -346
      ports/cabbage/source/Plugin/CabbagePluginProcessor.h
  41. +272
    -113
      ports/cabbage/source/Soundfiler.cpp
  42. +59
    -164
      ports/cabbage/source/Soundfiler.h
  43. +1373
    -0
      ports/cabbage/source/Table.cpp
  44. +357
    -0
      ports/cabbage/source/Table.h
  45. +460
    -438
      ports/cabbage/source/XYPad.cpp
  46. +195
    -188
      ports/cabbage/source/XYPad.h
  47. +131
    -121
      ports/cabbage/source/XYPadAutomation.cpp
  48. +63
    -61
      ports/cabbage/source/XYPadAutomation.h
  49. +207
    -180
      ports/cabbage/source/csPerfThread.cpp
  50. +32
    -23
      ports/cabbage/source/csPerfThread.hpp

+ 684
- 671
ports/cabbage/source/BinaryData.cpp
File diff suppressed because it is too large
View File


+ 26
- 26
ports/cabbage/source/BinaryData.h View File

@@ -1,26 +1,26 @@
/* =========================================================================================
This is an auto-generated file: Any edits you make may be overwritten!
*/
#ifndef BINARYDATA_INCLUDED
#define BINARYDATA_INCLUDED
namespace BinaryData
{
extern const char* cabbageLogoHBlueText_png;
const int cabbageLogoHBlueText_pngSize = 7732;
extern const char* logo_cabbage_Black_png;
const int logo_cabbage_Black_pngSize = 32229;
extern const char* logo_cabbage_black_no_text_png;
const int logo_cabbage_black_no_text_pngSize = 7710;
// If you provide the name of one of the binary resource variables above, this function will
// return the corresponding data and its size (or a null pointer if the name isn't found).
const char* getNamedResource (const char* resourceNameUTF8, int& dataSizeInBytes) throw();
}
#endif
/* =========================================================================================
This is an auto-generated file: Any edits you make may be overwritten!
*/
#ifndef BINARYDATA_INCLUDED
#define BINARYDATA_INCLUDED
namespace BinaryData
{
extern const char* cabbageLogoHBlueText_png;
const int cabbageLogoHBlueText_pngSize = 7732;
extern const char* logo_cabbage_Black_png;
const int logo_cabbage_Black_pngSize = 32229;
extern const char* logo_cabbage_black_no_text_png;
const int logo_cabbage_black_no_text_pngSize = 7710;
// If you provide the name of one of the binary resource variables above, this function will
// return the corresponding data and its size (or a null pointer if the name isn't found).
const char* getNamedResource (const char* resourceNameUTF8, int& dataSizeInBytes) throw();
}
#endif

+ 15
- 13
ports/cabbage/source/CabbageCallOutBox.cpp View File

@@ -18,7 +18,7 @@ CabbageCallOutBox::CabbageCallOutBox (Component& c, const Rectangle<int>& area,
{
setAlwaysOnTop (true);
updatePosition (area, Desktop::getInstance().getDisplays()
.getDisplayContaining (area.getCentre()).userArea);
.getDisplayContaining (area.getCentre()).userArea);
addToDesktop (ComponentPeer::windowIsTemporary);
}
@@ -48,8 +48,8 @@ public:
};
CabbageCallOutBox& CabbageCallOutBox::launchAsynchronously (Component* content,
const Rectangle<int>& area,
Component* parent)
const Rectangle<int>& area,
Component* parent)
{
jassert (content != nullptr); // must be a valid content component!
@@ -60,7 +60,7 @@ CabbageCallOutBox& CabbageCallOutBox::launchAsynchronously (Component* content,
void CabbageCallOutBox::paint (Graphics& g)
{
g.fillAll(Colours::black);
g.fillAll(Colours::black);
// getLookAndFeel().drawCallOutBoxBackground (*this, g, outline, background);
}
@@ -144,12 +144,14 @@ void CabbageCallOutBox::updatePosition (const Rectangle<int>& newAreaToPointTo,
Point<float> targets[4] = { Point<float> ((float) targetArea.getCentreX(), (float) targetArea.getBottom()),
Point<float> ((float) targetArea.getRight(), (float) targetArea.getCentreY()),
Point<float> ((float) targetArea.getX(), (float) targetArea.getCentreY()),
Point<float> ((float) targetArea.getCentreX(), (float) targetArea.getY()) };
Point<float> ((float) targetArea.getCentreX(), (float) targetArea.getY())
};
Line<float> lines[4] = { Line<float> (targets[0].translated (-hwReduced, hh - arrowIndent), targets[0].translated (hwReduced, hh - arrowIndent)),
Line<float> (targets[1].translated (hw - arrowIndent, -hhReduced), targets[1].translated (hw - arrowIndent, hhReduced)),
Line<float> (targets[2].translated (-(hw - arrowIndent), -hhReduced), targets[2].translated (-(hw - arrowIndent), hhReduced)),
Line<float> (targets[3].translated (-hwReduced, -(hh - arrowIndent)), targets[3].translated (hwReduced, -(hh - arrowIndent))) };
Line<float> (targets[3].translated (-hwReduced, -(hh - arrowIndent)), targets[3].translated (hwReduced, -(hh - arrowIndent)))
};
const Rectangle<float> centrePointArea (newAreaToFitIn.reduced (hw, hh).toFloat());
const Point<float> targetCentre (targetArea.getCentre().toFloat());
@@ -186,12 +188,12 @@ void CabbageCallOutBox::refreshPath()
background = Image::null;
outline.clear();
outline.addRectangle(1, 1, getWidth()-2, getHeight()-2);
/*
const float gap = 4.5f;
outline.addRectangle(1, 1, getWidth()-2, getHeight()-2);
/*
const float gap = 4.5f;
outline.addBubble (content.getBounds().toFloat().expanded (gap, gap),
getLocalBounds().toFloat(),
targetPoint - getPosition().toFloat(),
9.0*/
outline.addBubble (content.getBounds().toFloat().expanded (gap, gap),
getLocalBounds().toFloat(),
targetPoint - getPosition().toFloat(),
9.0*/
}

+ 7
- 7
ports/cabbage/source/CabbageCallOutBox.h View File

@@ -27,15 +27,15 @@ class CabbageCallOutBox : public Component
public:
//==============================================================================
CabbageCallOutBox (Component& contentComponent,
const Rectangle<int>& areaToPointTo,
Component* parentComponent);
const juce::Rectangle<int>& areaToPointTo,
Component* parentComponent);
~CabbageCallOutBox();

void updatePosition (const Rectangle<int>& newAreaToPointTo,
const Rectangle<int>& newAreaToFitIn);
void updatePosition (const juce::Rectangle<int>& newAreaToPointTo,
const juce::Rectangle<int>& newAreaToFitIn);
static CabbageCallOutBox& launchAsynchronously (Component* contentComponent,
const Rectangle<int>& areaToPointTo,
Component* parentComponent);
const juce::Rectangle<int>& areaToPointTo,
Component* parentComponent);

//==============================================================================
void paint (Graphics& g);
@@ -54,7 +54,7 @@ private:
Component& content;
Path outline;
Point<float> targetPoint;
Rectangle<int> availableArea, targetArea;
juce::Rectangle<int> availableArea, targetArea;
Image background;

void refreshPath();


+ 1706
- 1994
ports/cabbage/source/CabbageCustomWidgets.h
File diff suppressed because it is too large
View File


+ 1913
- 1751
ports/cabbage/source/CabbageGUIClass.cpp
File diff suppressed because it is too large
View File


+ 308
- 258
ports/cabbage/source/CabbageGUIClass.h View File

@@ -15,7 +15,7 @@
License along with Csound; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
*/
#ifndef CABBPARSE_H
#define CABBPARSE_H
@@ -32,273 +32,323 @@
#include "CabbageUtils.h"
//creating this as a singleton as I don't wish to create
//this array over and oer again when dealing with the CabbageGUIClass
//objects.
class IdentArray : public StringArray
{
public:
IdentArray() : StringArray("tablecolour")
{
add("tablecolours");
add("bounds");
add("fontcolour");
add("size");
add("items");
add("pos");
add("min");
add("max");
add("value");
add("tabpage");
add("guirefresh");
add("midictrl");
add("stack");
add("line");
add("populate");
add("range");
add("amprange");
add("rangex");
add("rangey");
add("plant");
add("channeltype");
add("channels");
add("channel");
add("channelarray");
add("identchannelarray");
add("name");
add("textbox");
add("caption");
add("kind");
add("config");
add("align");
add("beveltype");
add("wrap");
//add(" mode(");
//add(",mode(");
add("mode");
add("tablenumber");
add("tablenum");
add("tablenumbers");
add("tablenums");
add("fill");
add("logger");
add("file");
add("outlinecolour");
add("master");
add("shape");
add("textcolour");
add("scale");
add("key(");
add("pluginid");
add("trackercolour");
add("preset");
add("popup");
add("include");
add("show");
add("author");
add("drawmode");
add("resizemode");
add("readonly");
add("latched");
add("identchannel");
add("visible");
add("scrubberposition");
add("scroll");
add("zoom");
add("samplerange");
add("scrollbars");
add("socket");
//colour and text must go at end to prevent fall through
add("colour");
add("text");
}
~IdentArray()
{
// this ensures that no dangling pointers are left when the
// singleton is deleted.
clearSingletonInstance();
}
juce_DeclareSingleton (IdentArray, false)
};
namespace CabbageIDs
{
static const Identifier top = "top";
static const Identifier left = "left";
static const Identifier width = "width";
static const Identifier height = "height";
static const Identifier min = "min";
static const Identifier max = "max";
static const Identifier value = "value";
static const Identifier channel = "channel";
static const Identifier colour = "colour";
static const Identifier tablecolour = "tablecolour";
static const Identifier fontcolour= "fontcolour";
static const Identifier items = "items";
static const Identifier text = "text";
static const Identifier range = "range";
static const Identifier sliderrange = "sliderrange";
static const Identifier amprange = "amprange";
static const Identifier caption = "caption";
static const Identifier basetype = "basetype";
static const Identifier textbox = "textbox";
static const Identifier name = "name";
static const Identifier type = "type";
static const Identifier trackercolour = "trackercolour";
static const Identifier sliderskew = "sliderskew";
static const Identifier sliderincr = "sliderince";
static const Identifier midichan = "midichan";
static const Identifier midictrl = "midictrl";
static const Identifier kind = "kind";
static const Identifier decimalplaces = "decimalplaces";
static const Identifier mode = "mode";
static const Identifier shape = "shape";
static const Identifier channeltype = "channeltype";
static const Identifier comborange = "comborange";
static const Identifier populate = "populate";
static const Identifier outline = "outline";
static const Identifier popup = "popup";
static const Identifier plant = "plant";
static const Identifier line = "line";
static const Identifier tablenumber = "tablenumber";
static const Identifier resizemode = "resizemode";
static const Identifier drawmode = "drawmode";
static const Identifier readonly = "readonly";
static const Identifier xyautoindex = "xyautoindex";
static const Identifier file = "file";
static const Identifier latched = "latched";
static const Identifier xchannel = "xchannel";
static const Identifier ychannel = "ychannel";
static const Identifier minx = "minx";
static const Identifier miny = "miny";
static const Identifier maxx = "maxx";
static const Identifier maxy = "maxy";
static const Identifier valuex = "valuex";
static const Identifier fill = "fill";
static const Identifier valuey = "valuey";
static const Identifier textcolour = "textcolour";
static const Identifier pluginid = "pluginid";
static const Identifier tabs = "tabs";
static const Identifier tabbed = "tabbed";
static const Identifier rangey = "rangey";
static const Identifier rangex = "rangex";
static const Identifier tabpage = "tabpage";
static const Identifier filetype = "filetype";
static const Identifier workingdir = "workingdir";
static const Identifier author = "author";
static const Identifier xychannel = "xychannel";
static const Identifier guirefresh = "guirefresh";
//type of widgets/controls/messages
static const String combobox = "combobox";
static const String rslider = "rslider";
static const String hslider = "hslider";
static const String vslider = "vslider";
static const String checkbox = "checkbox";
static const String button = "button";
static const String filebutton = "filebutton";
static const String table = "table";
static const String groupbox = "groupbox";
static const String image = "image";
static const String form = "form";
static const String xypad = "xypad";
static const String stringchannel = "string";
static const String hostbpm = "HOST_BPM";
static const String timeinseconds = "TIME_IN_SECONDS";
static const String isplaying = "IS_PLAYING";
static const String isrecording = "IS_RECORDING";
static const String hostppqpos = "HOST_PPQ_POS";
static const String csoundoutput = "csoundoutput";
//identifiers
static const Identifier top = "top";
static const Identifier left = "left";
static const Identifier width = "width";
static const Identifier height = "height";
static const Identifier min = "min";
static const Identifier max = "max";
static const Identifier value = "value";
static const Identifier channel = "channel";
static const Identifier channelarray = "channelarray";
static const Identifier identchannelarray = "identchannelarray";
static const Identifier outlinecolour = "outlinecolour";
static const Identifier fillcolour = "fillcolour";
static const Identifier textcolour = "textcolour";
static const Identifier trackercolour = "trackercolour";
static const Identifier tablecolour = "tablecolour";
static const Identifier fontcolour= "fontcolour";
static const Identifier colour = "colour";
static const Identifier items = "items";
static const Identifier text = "text";
static const Identifier range = "range";
static const Identifier sliderrange = "sliderrange";
static const Identifier amprange = "amprange";
static const Identifier caption = "caption";
static const Identifier basetype = "basetype";
static const Identifier textbox = "textbox";
static const Identifier name = "name";
static const Identifier type = "type";
static const Identifier sliderskew = "sliderskew";
static const Identifier sliderincr = "sliderincr";
static const Identifier midichan = "midichan";
static const Identifier midictrl = "midictrl";
static const Identifier kind = "kind";
static const Identifier decimalplaces = "decimalplaces";
static const Identifier mode = "mode";
static const Identifier shape = "shape";
static const Identifier channeltype = "channeltype";
static const Identifier comborange = "comborange";
static const Identifier populate = "populate";
static const Identifier popup = "popup";
static const Identifier plant = "plant";
static const Identifier line = "line";
static const Identifier tablenumber = "tablenumber";
static const Identifier tableconfig = "tableconfig";
static const Identifier resizemode = "resizemode";
static const Identifier drawmode = "drawmode";
static const Identifier readonly = "readonly";
static const Identifier xyautoindex = "xyautoindex";
static const Identifier file = "file";
static const Identifier latched = "latched";
static const Identifier xchannel = "xchannel";
static const Identifier ychannel = "ychannel";
static const Identifier minx = "minx";
static const Identifier miny = "miny";
static const Identifier maxx = "maxx";
static const Identifier maxy = "maxy";
static const Identifier logger = "logger";
static const Identifier stack = "stack";
static const Identifier valuex = "valuex";
static const Identifier valuey = "valuey";
static const Identifier pluginid = "pluginid";
static const Identifier tabs = "tabs";
static const Identifier wrap = "wrap";
static const Identifier align = "align";
static const Identifier tabbed = "tabbed";
static const Identifier rangey = "rangey";
static const Identifier rangex = "rangex";
static const Identifier include = "include";
static const Identifier tabpage = "tabpage";
static const Identifier filetype = "filetype";
static const Identifier workingdir = "workingdir";
static const Identifier author = "author";
static const Identifier xychannel = "xychannel";
static const Identifier guirefresh = "guirefresh";
static const Identifier identchannel = "identchannel";
static const Identifier identchannelmessage = "identchannelmessage";
static const Identifier visible = "visible";
static const Identifier lineNumber = "linenumber";
static const Identifier scrubberposition = "scrubberposition";
static const Identifier startpoint = "startpoint";
static const Identifier endpoint = "endpoint";
static const Identifier zoom = "zoom";
static const Identifier visiblelength = "visiblelength";
static const Identifier samplerange = "samplerange";
static const Identifier startpos = "startpos";
static const Identifier endpos = "endpos";
static const Identifier show = "show";
static const Identifier child = "child";
static const Identifier scrollbars = "scrollbars";
static const Identifier oscport = "oscport";
static const Identifier oscaddress = "oscaddress";
//type of widgets/controls/messages
static const String combobox = "combobox";
static const String numberbox = "numberbox";
static const String rslider = "rslider";
static const String hslider = "hslider";
static const String vslider = "vslider";
static const String checkbox = "checkbox";
static const String soundfiler = "sounfiler";
static const String button = "button";
static const String infobutton = "infobutton";
static const String filebutton = "filebutton";
static const String texteditor = "texteditor";
static const String table = "table";
static const String gentable = "gentable";
static const String groupbox = "groupbox";
static const String image = "image";
static const String popupmenu = "popupmenu";
static const String label = "label";
static const String keyboard = "keyboard";
static const String oscserver = "oscserver";
static const String form = "form";
static const String directorylist = "directorylist";
static const String index = "index";
static const String xypad = "xypad";
static const String stringchannel = "string";
static const String hostbpm = "HOST_BPM";
static const String timeinseconds = "TIME_IN_SECONDS";
static const String isplaying = "IS_PLAYING";
static const String isrecording = "IS_RECORDING";
static const String hostppqpos = "HOST_PPQ_POS";
static const String mousex = "MOUSE_X";
static const String mousey = "MOUSE_Y";
static const String mousedownleft = "MOUSE_DOWN_LEFT";
static const String mousedownright = "MOUSE_DOWN_RIGHT";
static const String mousedownlmiddle = "MOUSE_DOWN_MIDDLE";
static const String csoundoutput = "csoundoutput";
};
class CabbageGUIClass : public CabbageUtils
{
double width, height, top, left, isRect, min, max, minX, minY, maxX, tabbed, maxY, comboRange, fftSize, overlapSize, frameSize,
noOfMenus, onoff, midiChan, midiCtrl, sliderRange, xypadRangeY, xypadRangeX, noSteps, noPatterns, pvsChannel, alpha,
line, anchor, linkTo, scaleX, scaleY, value, valueX, valueY, maxItems, sliderIncr, sliderSkew, decimalPlaces, rCtrls, lineIsVertical;
StringArray items, onoffcaptions, key, channels, snapshotData, colours;
String channel, name, sizeText, posText, boundsText, text, type, plant, reltoplant, bounds, range, fileType, workingDir,
shape, beveltype, caption, kind, topitem, yChannel, xChannel, author, native, basetype,
exit, csstdout, cssetup, file, debugMessage, xyChannel, pluginID, tabpage, preset;
Colour outline, fill, fontcolour, textcolour, colour, trackerFill;
int tableNum, textBox, numPresets, masterSnap, plantButton, xyAutoIndex, paramIndex, numTables, soundfilerIndex;
Array<int> vuConfig;
Array<int> tableNumbers;
Array<float> tableChannelValues;
//JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CabbageGUIClass);
double width, height, top, left;
/*, isRect, min, max, minX, minY, maxX, tabbed, maxY, comboRange, fftSize, overlapSize, frameSize,
noOfMenus, onoff, midiChan, midiCtrl, sliderRange, xypadRangeY, xypadRangeX, noSteps, noPatterns, pvsChannel, alpha,
line, anchor, linkTo, scaleX, scaleY, value, valueX, valueY, maxItems, sliderIncr, sliderSkew, decimalPlaces, rCtrls, lineIsVertical;
StringArray items, onoffcaptions, key, channels, snapshotData, colours;*/
Array<int> vuConfig;
Array<int> tableNumbers;
Array<float> tableChannelValues;
//JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CabbageGUIClass);
public:
//constructor
NamedValueSet cabbageIdentifiers;
CabbageGUIClass(String str, int ID);
CabbageGUIClass(){};
//constructor
NamedValueSet cabbageIdentifiers;
CabbageGUIClass(String str, int ID);
CabbageGUIClass() {};
~CabbageGUIClass();
int parse(String str);
float getNumProp(Identifier prop);
float getNumProp(Identifier prop, int index);
void setNumProp(Identifier prop, float val);
void setTableChannelValues(int index, float val);
float getTableChannelValues(int index);
void addTableChannelValues();
void setStringProp(Identifier prop, String val);
void setStringProp(Identifier prop, int index, String value);
String getStringProp(Identifier prop);
String getStringProp(Identifier prop, int index);
String getPropsString();
String getColourProp(Identifier prop);
float getNumPropVal(Identifier prop);
void setNumPropVal(Identifier prop, float val);
static String getCabbageCodeFromIdentifiers(NamedValueSet props);
static String getStringForIdentifier(var props, String identifier, String type);
Rectangle<int> getBounds(){
Rectangle<int> bounds(left, top, width, height);
return bounds;
}
void setBounds(Rectangle<int> bounds){
left = bounds.getX();
top = bounds.getY();
width = bounds.getWidth();
height = bounds.getHeight();
}
static StringArray getIdentifiers(){
StringArray test;
return test;
}
Rectangle<int> getComponentBounds();
StringArray getStringArrayProp(Identifier prop);
String getStringArrayPropValue(Identifier prop, int index);
int getIntArrayPropValue(Identifier prop, int index);
Array<int> getIntArrayProp(Identifier prop);
float getFloatArrayPropValue(Identifier prop, int index);
Array<float> getFloatArrayProp(Identifier prop);
StringArray getChannels(){
return channels;
}
inline int getNumPresets(){
return snapshotData.size();
}
inline void clearPresets(){
snapshotData.clear();
}
inline String setOnOffcaptions(int index, String str){
if(index<=onoffcaptions.size())
onoffcaptions.getReference(index)=str;
}
inline String getOnOffcaptions(int index){
if(index<=onoffcaptions.size())
return onoffcaptions.getReference(index);
else return "";
}
inline String setItems(int index, String str){
if(index<=items.size())
items.getReference(index)=str;
else
return "";
}
inline String getItems(int index){
if(isPositiveAndBelow (index, items.size()))
return items.getReference(index);
else return "";
}
inline String getColours(int index){
if(colours.size())
return colours.getReference(index);
else return "";
}
inline int getNumberOfColours(){
return colours.size();
}
inline StringArray getItemArray(){
if(items.size())
return items;
else return StringArray();
}
inline int getItemsSize(){
return items.size();
}
inline Array<int> getVUConfig(){
return vuConfig;
}
// inline String getChannel(int index){
// return channels[index];
// }
inline void addDummyChannel(String dummyChan){
return channels.add(dummyChan);
}
// inline String getTableChannel(int index){
// return channels[index];
// }
// inline int getNumberOfTableChannels(){
// return channels.size();
// }
inline int getKeySize(){
return key.size();
}
inline String getkey(int index){
return key.getReference(index);
}
// inline int getNumberOfTables(){
// return numTables;
// }
// int getTableNumbers(int index)
// {
// if(index<tableNumbers.size())
// return tableNumbers[index];
// }
// inline Array<int> getTableNumbersArray()
// {
// return tableNumbers;
// }
int parse(String str, String identifier);
float getNumProp(Identifier prop);
float getNumProp(Identifier prop, int index);
void setNumProp(Identifier prop, float val);
void setTableChannelValues(int index, float val);
float getTableChannelValues(int index);
void addTableChannelValues();
void setStringProp(Identifier prop, String val);
void setStringProp(Identifier prop, int index, String value);
String getStringProp(Identifier prop);
String getStringProp(Identifier prop, int index);
String getPropsString();
String getColourProp(Identifier prop);
float getNumPropVal(Identifier prop);
void setNumPropVal(Identifier prop, float val);
static String getCabbageCodeFromIdentifiers(NamedValueSet props);
static String getStringForIdentifier(var props, String identifier, String type);
Rectangle<int> getBounds()
{
Rectangle<int> bounds(left, top, width, height);
return bounds;
}
//static methods used for updating look and pos of GUI controls
static Rectangle<int> getBoundsFromText(String text);
static Colour getColourFromText(String text);
static String getTextFromText(String text);
static Point<int> getSizeFromText(String text);
static Point<int> getPosFromText(String text);
static float getSkewFromText(String text);
static var getVarArrayFromText(String text);
void setBounds(Rectangle<int> bounds)
{
left = bounds.getX();
top = bounds.getY();
width = bounds.getWidth();
height = bounds.getHeight();
}
static StringArray getIdentifiers()
{
StringArray test;
return test;
}
Rectangle<int> getComponentBounds();
StringArray getStringArrayProp(Identifier prop);
String getStringArrayPropValue(Identifier prop, int index);
int getIntArrayPropValue(Identifier prop, int index);
Array<int> getIntArrayProp(Identifier prop);
var getVarArrayProp(Identifier prop);
float getFloatArrayPropValue(Identifier prop, int index);
Array<float> getFloatArrayProp(Identifier prop);
void setStringArrayPropValue(Identifier prop, int index, String value);
void setStringArrayProp(Identifier prop, var value);
};
#endif
#endif

+ 1551
- 1446
ports/cabbage/source/CabbageLookAndFeel.cpp
File diff suppressed because it is too large
View File


+ 173
- 156
ports/cabbage/source/CabbageLookAndFeel.h View File

@@ -16,97 +16,101 @@
class CabbageLookAndFeel : public LookAndFeel_V2
{
public:
CabbageLookAndFeel();
~CabbageLookAndFeel();
Image drawRotaryImage(int diameter, const Colour circleFill, const Colour trackerCol, float sliderPosProportional, float zeroPosProportional,
bool useTrackerFill,
float markerOpacity);
Image drawLinearBgImage (float width, float height, float sliderPosProportional, float zeroPosProportional,
bool useTrackerFill,
bool isVertical,
const Colour trackerCol);
void drawTableHeaderColumn (Graphics& g, const String& columnName, int /*columnId*/,
int width, int height,
bool isMouseOver, bool isMouseDown,
int columnFlags);
void drawTableHeaderBackground (Graphics& g, TableHeaderComponent& header);
Image drawLinearThumbImage (float width, float height, const Colour thumbFill, bool isVertical);
static Image drawToggleImage (float width, float height, bool isToggleOn, Colour colour, bool isRect);
Image drawTextButtonImage (float width, float height, bool isButtonDown, Colour colour);
virtual void drawRotarySlider (Graphics &g, int x, int y, int width, int height, float sliderPosProportional,
float rotaryStartAngle,
float rotaryEndAngle,
Slider &slider);
virtual void drawLinearSliderBackground (Graphics &g, int x, int y, int width, int height,
float sliderPos,
float minSliderPos,
float maxSliderPos,
const Slider::SliderStyle style,
Slider &slider);
virtual void drawLinearSliderThumb (Graphics &g, int x, int y, int width, int height, float sliderPos,
float minSliderPos,
float maxSliderPos,
const Slider::SliderStyle style,
Slider &slider);
virtual void drawButtonBackground (Graphics&, Button&, const Colour&, bool, bool);
virtual void drawButtonText (Graphics &g, TextButton &button, bool isMouseOverButton, bool isButtonDown);
virtual void drawLabel (Graphics &g, Label &label);
virtual void drawComboBox (Graphics&, int, int, bool, int, int, int, int, ComboBox&);
virtual void drawToggleButton (Graphics &g, ToggleButton &button, bool isMouseOverButton, bool isButtonDown);
virtual void drawTextEditorOutline (Graphics &g, int width, int height, TextEditor &textEditor);
virtual void fillTextEditorBackground (Graphics &g, int width, int height, TextEditor &textEditor);
virtual void drawGroupComponentOutline (Graphics &g, int w, int h, const String &text, const Justification &position,
GroupComponent &group);
virtual int getDefaultScrollbarWidth();
virtual void drawScrollbar (Graphics &g, ScrollBar &scrollbar, int x, int y, int width, int height,
bool isScrollbarVertical,
int thumbStartPosition,
int thumbSize,
bool isMouseOver,
bool isMouseDown);
virtual void drawScrollbarButton (Graphics &g, ScrollBar &scrollbar, int width, int height, int buttonDirection,
bool isScrollbarVertical,
bool isMouseOverButton,
bool isButtonDown);
void setDefaultSansSerifTypefaceName (const String &newName);
virtual void drawMenuBarBackground(Graphics &g, int width, int height, bool isMouseOverBar, MenuBarComponent &menuBar);
CabbageLookAndFeel();
~CabbageLookAndFeel();
Image getSVGImageFor(String type);
Image drawRotaryImage(int diameter, const Colour circleFill, const Colour trackerCol, float sliderPosProportional, float zeroPosProportional,
bool useTrackerFill,
float markerOpacity);
Image drawLinearBgImage (float width, float height, float sliderPosProportional, float zeroPosProportional,
bool useTrackerFill,
bool isVertical,
const Colour trackerCol);
void drawTableHeaderColumn (Graphics& g, const String& columnName, int /*columnId*/,
int width, int height,
bool isMouseOver, bool isMouseDown,
int columnFlags);
void drawTableHeaderBackground (Graphics& g, TableHeaderComponent& header);
Image drawLinearThumbImage (float width, float height, const Colour thumbFill, bool isVertical);
static Image drawToggleImage (float width, float height, bool isToggleOn, Colour colour, bool isRect);
Image drawTextButtonImage (float width, float height, bool isButtonDown, Colour colour);
virtual void drawRotarySlider (Graphics &g, int x, int y, int width, int height, float sliderPosProportional,
float rotaryStartAngle,
float rotaryEndAngle,
Slider &slider);
virtual void drawLinearSliderBackground (Graphics &g, int x, int y, int width, int height,
float sliderPos,
float minSliderPos,
float maxSliderPos,
const Slider::SliderStyle style,
Slider &slider);
virtual void drawLinearSliderThumb (Graphics &g, int x, int y, int width, int height, float sliderPos,
float minSliderPos,
float maxSliderPos,
const Slider::SliderStyle style,
Slider &slider);
virtual void drawButtonBackground (Graphics&, Button&, const Colour&, bool, bool);
virtual void drawButtonText (Graphics &g, TextButton &button, bool isMouseOverButton, bool isButtonDown);
virtual void drawLabel (Graphics &g, Label &label);
virtual void drawComboBox (Graphics&, int, int, bool, int, int, int, int, ComboBox&);
virtual Font getComboBoxFont (ComboBox& box);
virtual Label* createComboBoxTextBox (ComboBox&);
void positionComboBoxText (ComboBox& box, Label& label);
virtual void drawToggleButton (Graphics &g, ToggleButton &button, bool isMouseOverButton, bool isButtonDown);
virtual void drawTextEditorOutline (Graphics &g, int width, int height, TextEditor &textEditor);
virtual void fillTextEditorBackground (Graphics &g, int width, int height, TextEditor &textEditor);
virtual void drawGroupComponentOutline (Graphics &g, int w, int h, const String &text, const Justification &position,
GroupComponent &group);
virtual int getDefaultScrollbarWidth();
int getMinimumScrollbarThumbSize(){return 15;}
virtual void drawScrollbar (Graphics &g, ScrollBar &scrollbar, int x, int y, int width, int height,
bool isScrollbarVertical,
int thumbStartPosition,
int thumbSize,
bool isMouseOver,
bool isMouseDown);
virtual void drawScrollbarButton (Graphics &g, ScrollBar &scrollbar, int width, int height, int buttonDirection,
bool isScrollbarVertical,
bool isMouseOverButton,
bool isButtonDown);
void setDefaultSansSerifTypefaceName (const String &newName);
virtual void drawMenuBarBackground(Graphics &g, int width, int height, bool isMouseOverBar, MenuBarComponent &menuBar);
virtual void drawMenuBarItem(Graphics & g, int width, int height, int itemIndex,
const String &itemText, bool isMouseOverItem,
bool isMenuOpen, bool isMouseOverBar,
MenuBarComponent &menuBar);
void drawPopupMenuBackground(Graphics &g, int width, int height);
Image drawCheckMark();
virtual void drawPopupMenuItem (Graphics &g, int width, int height, bool isSeparator, bool isActive, bool isHighlighted,
bool isTicked,
bool hasSubMenu,
const String &text,
const String &shortcutKeyText,
Image *image,
const Colour *const textColour);
virtual void drawDocumentWindowTitleBar (DocumentWindow &window, Graphics &g, int w, int h, int titleSpaceX, int titleSpaceW,
const Image *icon,
bool drawTitleTextOnLeft);
Image drawWindowButtonNormal(int buttonType);
Image drawWindowButtonIsOver(int buttonType);
virtual Button* createDocumentWindowButton (int buttonType);
int getAlertBoxWindowFlags();
int getAlertWindowButtonHeight();
Font getAlertWindowMessageFont();
Font getAlertWindowFont();
void drawAlertBox (Graphics& g, AlertWindow& alert, const Rectangle<int>& textArea, TextLayout& textLayout);
AlertWindow* createAlertWindow (const String& title, const String& message, const String& button1, const String& button2,
const String& button3, AlertWindow::AlertIconType iconType, int numButtons,
Component* associatedComponent);
int getTabButtonSpaceAroundImage();
const String &itemText, bool isMouseOverItem,
bool isMenuOpen, bool isMouseOverBar,
MenuBarComponent &menuBar);
void drawPopupMenuBackground(Graphics &g, int width, int height);
Image drawCheckMark();
virtual void drawPopupMenuItem (Graphics& g, const Rectangle<int>& area,
const bool isSeparator, const bool isActive,
const bool isHighlighted, const bool isTicked,
const bool hasSubMenu, const String& text,
const String& shortcutKeyText,
const Drawable* icon, const Colour* const textColourToUse);
virtual void drawDocumentWindowTitleBar (DocumentWindow &window, Graphics &g, int w, int h, int titleSpaceX, int titleSpaceW,
const Image *icon,
bool drawTitleTextOnLeft);
Image drawWindowButtonNormal(int buttonType);
Image drawWindowButtonIsOver(int buttonType);
virtual Button* createDocumentWindowButton (int buttonType);
int getAlertBoxWindowFlags();
int getAlertWindowButtonHeight();
Font getAlertWindowMessageFont();
Font getAlertWindowFont();
void drawAlertBox (Graphics& g, AlertWindow& alert, const Rectangle<int>& textArea, TextLayout& textLayout);
AlertWindow* createAlertWindow (const String& title, const String& message, const String& button1, const String& button2,
const String& button3, AlertWindow::AlertIconType iconType, int numButtons,
Component* associatedComponent);
int getTabButtonSpaceAroundImage();
int getTabButtonOverlap (int tabDepth);
int getTabButtonBestWidth (TabBarButton&, int tabDepth);
Rectangle<int> getTabButtonExtraComponentBounds (const TabBarButton&, Rectangle<int>& textArea, Component& extraComp);
@@ -119,26 +123,39 @@ public:
void fillTabButtonShape (TabBarButton&, Graphics& g, const Path& path, bool isMouseOver, bool isMouseDown);
void drawFileBrowserRow (Graphics& g, int width, int height,
const String& filename, Image* icon,
const String& fileSizeDescription,
const String& fileTimeDescription,
bool isDirectory,
bool isItemSelected,
int itemIndex,
DirectoryContentsDisplayComponent& component);
const String& filename, Image* icon,
const String& fileSizeDescription,
const String& fileTimeDescription,
bool isDirectory,
bool isItemSelected,
int itemIndex,
DirectoryContentsDisplayComponent& component);
void drawTreeviewPlusMinusBox (Graphics& g, int x, int y, int w, int h, bool isPlus, bool /*isMouseOver*/);
void drawTreeviewPlusMinusBox (Graphics& g, int x, int y, int w, int h, bool isPlus, bool /*isMouseOver*/);
void drawLevelMeter(Graphics &g, int width, int height, float level);
Button* createTabBarExtrasButton();
juce_UseDebuggingNewOperator
Button* createTabBarExtrasButton();
void drawLinearSlider (Graphics&, int x, int y, int width, int height,
float sliderPos, float minSliderPos, float maxSliderPos,
const Slider::SliderStyle, Slider&);
void drawStretchableLayoutResizerBar (Graphics& g, int w, int h,
bool /*isVerticalBar*/,
bool isMouseOver,
bool isMouseDragging);
int getDefaultMenuBarHeight(){
return 18;
}
juce_UseDebuggingNewOperator
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CabbageLookAndFeel);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CabbageLookAndFeel);
};
@@ -152,64 +169,64 @@ private:
class CabbageLookAndFeelBasic : public LookAndFeel_V2
{
public:
CabbageLookAndFeelBasic();
~CabbageLookAndFeelBasic();
void drawLabel(Graphics&, Label&);
virtual void drawLinearSliderBackground (Graphics &g, int x, int y, int width, int height,
float sliderPos,
float minSliderPos,
float maxSliderPos,
const Slider::SliderStyle style,
Slider &slider);
virtual void drawLinearSliderThumb (Graphics &g, int x, int y, int width, int height, float sliderPos,
float minSliderPos,
float maxSliderPos,
const Slider::SliderStyle style,
Slider &slider);
CabbageLookAndFeelBasic();
~CabbageLookAndFeelBasic();
void drawLabel(Graphics&, Label&);
virtual void drawLinearSliderBackground (Graphics &g, int x, int y, int width, int height,
float sliderPos,
float minSliderPos,
float maxSliderPos,
const Slider::SliderStyle style,
Slider &slider);
virtual void drawLinearSliderThumb (Graphics &g, int x, int y, int width, int height, float sliderPos,
float minSliderPos,
float maxSliderPos,
const Slider::SliderStyle style,
Slider &slider);
void drawButtonBackground (Graphics& g, Button& button, const Colour& backgroundColour, bool isMouseOverButton, bool isButtonDown);
virtual void drawScrollbar (Graphics &g, ScrollBar &scrollbar, int x, int y, int width, int height,
bool isScrollbarVertical,
int thumbStartPosition,
int thumbSize,
bool isMouseOver,
bool isMouseDown);
void drawDocumentWindowTitleBar (DocumentWindow &window, Graphics &g, int w, int h,
int /*titleSpaceX*/,
int titleSpaceW,
const Image */*icon*/,
bool /*drawTitleTextOnLeft*/);
void drawResizableWindowBorder (Graphics &g, int w, int h, const BorderSize< int > &border, ResizableWindow &window);
void drawPopupMenuBackground(Graphics &g, int width, int height);
void drawMenuBarBackground(Graphics &g, int width, int height, bool isMouseOverBar, MenuBarComponent &menuBar);
Image drawCheckMark();
void drawMenuBarItem(Graphics & g, int width, int height, int itemIndex,
const String &itemText,
bool isMouseOverItem,
bool isMenuOpen,
bool isMouseOverBar,
MenuBarComponent &menuBar);
void drawPopupMenuItem (Graphics &g, int width, int height, bool isSeparator, bool /*isActive*/,
bool isHighlighted,
bool isTicked,
bool hasSubMenu,
const String &text,
const String &shortcutKeyText,
Image */*image*/,
const Colour */*const textColour*/);
juce_UseDebuggingNewOperator
virtual void drawScrollbar (Graphics &g, ScrollBar &scrollbar, int x, int y, int width, int height,
bool isScrollbarVertical,
int thumbStartPosition,
int thumbSize,
bool isMouseOver,
bool isMouseDown);
void drawDocumentWindowTitleBar (DocumentWindow &window, Graphics &g, int w, int h,
int /*titleSpaceX*/,
int titleSpaceW,
const Image */*icon*/,
bool /*drawTitleTextOnLeft*/);
void drawResizableWindowBorder (Graphics &g, int w, int h, const BorderSize< int > &border, ResizableWindow &window);
void drawPopupMenuBackground(Graphics &g, int width, int height);
void drawMenuBarBackground(Graphics &g, int width, int height, bool isMouseOverBar, MenuBarComponent &menuBar);
Image drawCheckMark();
void drawMenuBarItem(Graphics & g, int width, int height, int itemIndex,
const String &itemText,
bool isMouseOverItem,
bool isMenuOpen,
bool isMouseOverBar,
MenuBarComponent &menuBar);
void drawPopupMenuItem (Graphics &g, int width, int height, bool isSeparator, bool /*isActive*/,
bool isHighlighted,
bool isTicked,
bool hasSubMenu,
const String &text,
const String &shortcutKeyText,
Image */*image*/,
const Colour */*const textColour*/);
juce_UseDebuggingNewOperator
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CabbageLookAndFeelBasic);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CabbageLookAndFeelBasic);
};


+ 42
- 42
ports/cabbage/source/CabbageMainPanel.cpp View File

@@ -1,43 +1,43 @@
/*
Copyright (C) 2007 Rory Walsh
Cabbage is free software; you can redistribute it
and/or modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
Cabbage is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with Csound; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
*/
#include "CabbageMainPanel.h"
#include "ComponentLayoutEditor.h"
/*
Copyright (C) 2007 Rory Walsh
Cabbage is free software; you can redistribute it
and/or modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
Cabbage is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with Csound; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
*/
#include "CabbageMainPanel.h"
#include "ComponentLayoutEditor.h"
// This is the main panel/component onto which all other components are drawn.
// When users drop components onto this panel, ComponentLayoutEditor will
// When users drop components onto this panel, ComponentLayoutEditor will
// create aliases of each so that they can be moved around and resized.
// When a user disables the ComponentLayoutEditor this panel is again brought
// to front so that components can no longer be edited. The idea is that
// by toggling these two classes toFront() we can swap between edit and lock mode
CabbageMainPanel::CabbageMainPanel() : width(-99), top(-99), height(-99), left(-99)
{
setName("CabbageMainPanel");
setVisible(true);
setSize(0,0);
LOCKED=true;
panelColour = CabbageUtils::getBackgroundSkin();
setName("CabbageMainPanel");
setVisible(true);
setSize(0,0);
LOCKED=true;
panelColour = CabbageUtils::getBackgroundSkin();
}
CabbageMainPanel::~CabbageMainPanel()
{
@@ -46,23 +46,23 @@ CabbageMainPanel::~CabbageMainPanel()
void CabbageMainPanel::paint(Graphics &g)
{
}
ComponentLayoutEditor* CabbageMainPanel::getLayoutEditor()
{
return layoutEditor;
return layoutEditor;
}
void CabbageMainPanel::setLayoutEditor(ComponentLayoutEditor* ed)
{
jassert (ed);
if (layoutEditor)
{
// deleteAndZero (layoutEditor);
}
layoutEditor = ed;
jassert (ed);
if (layoutEditor)
{
// deleteAndZero (layoutEditor);
}
layoutEditor = ed;
}

+ 115
- 102
ports/cabbage/source/CabbageMainPanel.h View File

@@ -32,112 +32,125 @@ class ComponentLayoutEditor;
//-----------------------------------------------------------------------------
class CabbageMainPanel : public Component,
public CabbageUtils,
public ActionBroadcaster
public CabbageUtils,
public ActionBroadcaster
{
private:
ScopedPointer<ComponentLayoutEditor> layoutEditor;
OwnedArray<Component > comps;
OwnedArray<Component > clipBoard;
Colour panelColour;
int currentIndex;
bool LOCKED;
String mouseState;
String colour;
bool doubleClick;
private:
ScopedPointer<ComponentLayoutEditor> layoutEditor;
OwnedArray<Component > comps;
OwnedArray<Component > clipBoard;
Colour panelColour;
int currentIndex;
bool LOCKED;
String mouseState;
String colour;
bool doubleClick;
public:
Rectangle<int> currentBounds;
Array<Rectangle<int> > childBounds;
Array<Rectangle<int> > origChildBounds;
Array<Point<int> > origSelectedCompBounds;
Array<Point<int> > newSelectedCompBounds;
int width, height, top, left;
inline void setCompColour(String col){
colour = col;
}
inline String getColour(){
return colour;
}
inline String getMouseState(){
return mouseState;
}
inline void setMouseState(String state){
mouseState = state;
}
inline void setDoubleClick(bool dblClick){
doubleClick = dblClick;
}
bool isDoubleClick(){
return doubleClick;
}
//String getCurrentBounds(){
// return "bounds(" + String(currentBounds.getX()) + String(", ") + String(currentBounds.getY()) + String(", ") + String(currentBounds.getWidth()) + String(", ")
// + String(currentBounds.getHeight()) + String(")");
//}
//String getCurrentChildBounds(int i){
// return "bounds(" + String(childBounds[i].getX()) + String(", ") + String(childBounds[i].getY()) + String(", ") + String(childBounds[i].getWidth()) + String(", ")
// + String(childBounds[i].getHeight()) + String(")");
//}
//String getCurrentOrigChildBounds(int i){
// return "bounds(" + String(origChildBounds[i].getX()) + String(", ") + String(origChildBounds[i].getY()) + String(", ") + String(origChildBounds[i].getWidth()) + String(", ")
// + String(origChildBounds[i].getHeight()) + String(")");
//}
//
//String getCurrentPos(){
//return String("pos(") + String(left) + String(", ") + String(top) + String(")");
//}
String getCurrentSize(){
return String("size(") + String(width) + String(", ") + String(height) + String(")");
}
CabbageMainPanel();
~CabbageMainPanel();
void paint(Graphics &g);
ComponentLayoutEditor* getLayoutEditor();
void setLayoutEditor(ComponentLayoutEditor* ed);
inline int getIndex(){
return currentIndex;
}
int getCurrentWidth(){
return width;
}
int getCurrentHeight(){
return height;
}
int getCurrentTop(){
return top;
}
int getCurrentLeft(){
return left;
}
inline void setIndex(int index){
currentIndex = index;
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CabbageMainPanel);
juce::Rectangle<int> currentBounds;
Array<juce::Rectangle<int> > childBounds;
Array<juce::Rectangle<int> > origChildBounds;
Array<Point<int> > origSelectedCompBounds;
Array<Point<int> > newSelectedCompBounds;
int width, height, top, left;
inline void setCompColour(String col)
{
colour = col;
}
inline String getColour()
{
return colour;
}
inline String getMouseState()
{
return mouseState;
}
inline void setMouseState(String state)
{
mouseState = state;
}
inline void setDoubleClick(bool dblClick)
{
doubleClick = dblClick;
}
bool isDoubleClick()
{
return doubleClick;
}
//String getCurrentBounds(){
// return "bounds(" + String(currentBounds.getX()) + String(", ") + String(currentBounds.getY()) + String(", ") + String(currentBounds.getWidth()) + String(", ")
// + String(currentBounds.getHeight()) + String(")");
//}
//String getCurrentChildBounds(int i){
// return "bounds(" + String(childBounds[i].getX()) + String(", ") + String(childBounds[i].getY()) + String(", ") + String(childBounds[i].getWidth()) + String(", ")
// + String(childBounds[i].getHeight()) + String(")");
//}
//String getCurrentOrigChildBounds(int i){
// return "bounds(" + String(origChildBounds[i].getX()) + String(", ") + String(origChildBounds[i].getY()) + String(", ") + String(origChildBounds[i].getWidth()) + String(", ")
// + String(origChildBounds[i].getHeight()) + String(")");
//}
//
//String getCurrentPos(){
//return String("pos(") + String(left) + String(", ") + String(top) + String(")");
//}
String getCurrentSize()
{
return String("size(") + String(width) + String(", ") + String(height) + String(")");
}
CabbageMainPanel();
~CabbageMainPanel();
void paint(Graphics &g);
ComponentLayoutEditor* getLayoutEditor();
void setLayoutEditor(ComponentLayoutEditor* ed);
inline int getIndex()
{
return currentIndex;
}
int getCurrentWidth()
{
return width;
}
int getCurrentHeight()
{
return height;
}
int getCurrentTop()
{
return top;
}
int getCurrentLeft()
{
return left;
}
inline void setIndex(int index)
{
currentIndex = index;
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CabbageMainPanel);
};

+ 84
- 70
ports/cabbage/source/CabbageMessageSystem.h View File

@@ -16,89 +16,103 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
*/
*/
#ifndef CABBMESS_H
#define CABBMESS_H
#define CABBMESS_H
#include "CabbageUtils.h"
#ifndef Cabbage_No_Csound
#include "csound.hpp"
#endif

#ifdef AndroidBuild
#include "AndroidCsound.hpp"
#else
#include <csound.hpp>
#endif
#endif
using namespace std;


//simple channel message classe
class CabbageChannelMessage : public CabbageUtils
{
public:
String channelName;
String channelName;
#ifndef Cabbage_No_Csound
MYFLT value;
MYFLT value;
#else
float value;
float value;
#endif
String type;
String fStatement;
String stringVal;
CabbageChannelMessage(String chan, double val, String _type)
{
channelName = chan;
value = val;
type = _type;
}
CabbageChannelMessage(String chan, String val, String _type)
{
channelName = chan;
stringVal = val;
type = _type;
}
~CabbageChannelMessage()
{}
};

//message queue class
String type;
String fStatement;
int tableNumber;
String stringVal;
CabbageChannelMessage(String chan, double val, String _type)
{
channelName = chan;
value = val;
type = _type;
}
CabbageChannelMessage(String chan, String val, String _type)
{
channelName = chan;
stringVal = val;
type = _type;
}
~CabbageChannelMessage()
{}
};
//message queue class
class CabbageMessageQueue : public CabbageUtils
{
Array<CabbageChannelMessage> outgoingChannelMessages;
Array<CabbageChannelMessage, CriticalSection> outgoingChannelMessages;
public:
CabbageMessageQueue(){}
~CabbageMessageQueue(){}

void addOutgoingChannelMessageToQueue(String _chan, double _val, String _type){
outgoingChannelMessages.add(CabbageChannelMessage(_chan, _val, _type));
}
void addOutgoingChannelMessageToQueue(String _chan, String _val, String _type){
outgoingChannelMessages.add(CabbageChannelMessage(_chan, _val, _type));
}
void addOutgoingTableUpdateMessageToQueue(String fStatement){
CabbageChannelMessage tableMessage("", 0.f, "updateTable");
tableMessage.fStatement = fStatement;
outgoingChannelMessages.add(tableMessage);
}

CabbageChannelMessage getOutgoingChannelMessageFromQueue(int index){
return outgoingChannelMessages.getReference(index);
}

int getNumberOfOutgoingChannelMessagesInQueue(){
return outgoingChannelMessages.size();
}

void flushOutgoingChannelMessages(){
outgoingChannelMessages.clear();
}
};



CabbageMessageQueue() {}
~CabbageMessageQueue() {}
void addOutgoingChannelMessageToQueue(String _chan, double _val, String _type)
{
outgoingChannelMessages.add(CabbageChannelMessage(_chan, _val, _type));
}
void addOutgoingChannelMessageToQueue(String _chan, String _val, String _type)
{
outgoingChannelMessages.add(CabbageChannelMessage(_chan, _val, _type));
}
void addOutgoingTableUpdateMessageToQueue(String fStatement, int tableNumber)
{
CabbageChannelMessage tableMessage("", 0.f, "updateTable");
tableMessage.fStatement = fStatement;
tableMessage.tableNumber = tableNumber;
outgoingChannelMessages.add(tableMessage);
}
CabbageChannelMessage getOutgoingChannelMessageFromQueue(int index)
{
return outgoingChannelMessages.getReference(index);
}
int getNumberOfOutgoingChannelMessagesInQueue()
{
return outgoingChannelMessages.size();
}
void flushOutgoingChannelMessages()
{
//const MessageManagerLock mmLock;
outgoingChannelMessages.clear();
}
};
#endif

+ 66
- 61
ports/cabbage/source/CabbagePropertiesDialog.cpp View File

@@ -15,43 +15,47 @@
License along with Csound; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
*/

#include "CabbagePropertiesDialog.h"

ControlProperty::ControlProperty(String name, var _value):
PropertyComponent(name),
name(name),
value(_value)
ControlProperty::ControlProperty(String name, var _value):
PropertyComponent(name),
name(name),
value(_value)
{
if((name=="text" || name=="channel" || name=="items"
|| name=="drawmode" || name=="tablenumber")
|| name=="tablecolour" || name=="amprange"
|| name=="resizemode"){
addAndMakeVisible(textComboField = new TextComboField(name, value));
//textComboField->setLookAndFeel(lookAndFeel);
textComboField->addActionListener(this);
}
else if(name.contains("colour")){
addAndMakeVisible(colourField = new ColourField(name, value.toString()));
colourField->addActionListener(this);
colourField->repaint();
}
else if(name.contains("file") || name.contains("workingdir")){
addAndMakeVisible(fileBrowserField = new FileBrowserField(name, value.toString()));
fileBrowserField->addActionListener(this);
}
else{
addAndMakeVisible(textField = new TextField(name));
textField->addActionListener(this);
if(value.size()>0)
textField->setText(value[0]);
else
textField->setText(value);
setName(name);
}

if((name=="text" || name=="channel" || name=="items"
|| name=="drawmode" || name=="tablenumber")
|| name=="tablecolour" || name=="amprange"
|| name=="resizemode")
{
addAndMakeVisible(textComboField = new TextComboField(name, value));
//textComboField->setLookAndFeel(lookAndFeel);
textComboField->addActionListener(this);
}
else if(name.contains("colour"))
{
addAndMakeVisible(colourField = new ColourField(name, value.toString()));
colourField->addActionListener(this);
colourField->repaint();
}
else if(name=="file" || name=="workingdir")
{
addAndMakeVisible(fileBrowserField = new FileBrowserField(name, value.toString()));
fileBrowserField->addActionListener(this);
}
else
{
addAndMakeVisible(textField = new TextField(name));
textField->addActionListener(this);
if(value.size()>0)
textField->setText(value[0]);
else
textField->setText(value);
setName(name);
}

}

@@ -59,43 +63,44 @@ void ControlProperty::actionListenerCallback (const String& message)
{
//when a user clicks escape from a propery component this method is called.
//everytime this method is called we update the parameters
if(message=="ColourField")
value = colourField->value;
else if(message=="TextField")
value = textField->value;
else if(message=="TextComboField")
value = textComboField->value;
else if(message=="FileBrowserField")
value = fileBrowserField->value;
else if(message=="UpdateAll")
{
CabbagePropertiesDialog* parentWindow = findParentComponentOfClass <CabbagePropertiesDialog>();
if(parentWindow)
parentWindow->updateIdentifiers();
}
if(message=="ColourField")
value = colourField->value;
else if(message=="TextField")
value = textField->value;
else if(message=="TextComboField")
value = textComboField->value;
else if(message=="FileBrowserField")
value = fileBrowserField->value;
else if(message=="UpdateAll")
{
CabbagePropertiesDialog* parentWindow = findParentComponentOfClass <CabbagePropertiesDialog>();
if(parentWindow)
parentWindow->updateIdentifiers();
}
}

void ControlProperty::resized()
{
if(textField)textField->setBounds(getWidth()/2, 2.5, getWidth()/2-5, getHeight()-5);
if(textComboField)textComboField->setBounds(getWidth()/2, 2.5, getWidth()/2-5, getHeight()-5);
if(colourField)colourField->setBounds(getWidth()/2, 2.5, getWidth()/2-5, getHeight()-5);
if(fileBrowserField)fileBrowserField->setBounds(getWidth()/2, 2.5, getWidth()/2-5, getHeight()-5);
if(textField)textField->setBounds(getWidth()/2, 2.5, getWidth()/2-5, getHeight()-5);
if(textComboField)textComboField->setBounds(getWidth()/2, 2.5, getWidth()/2-5, getHeight()-5);
if(colourField)colourField->setBounds(getWidth()/2, 2.5, getWidth()/2-5, getHeight()-5);
if(fileBrowserField)fileBrowserField->setBounds(getWidth()/2, 2.5, getWidth()/2-5, getHeight()-5);
}


void ControlProperty::paint(Graphics &g){
g.setColour (Colour(10, 10, 10));
g.fillAll();
void ControlProperty::paint(Graphics &g)
{
g.setColour (Colour(10, 10, 10));
g.fillAll();

g.setColour (Colours::orange);
g.setFont (CabbageUtils::getComponentFont());
g.setColour (Colours::orange);
g.setFont (CabbageUtils::getComponentFont());

const Rectangle<int> r (5, 0, getWidth()/2, getHeight()-2);
const Rectangle<int> r (5, 0, getWidth()/2, getHeight()-2);

g.drawFittedText(name,
r,
Justification::centred, 2);
g.setColour (Colours::black);
g.drawRect(0, 0, getWidth(), getHeight(), 1);
g.drawFittedText(name,
r,
Justification::centred, 2);
g.setColour (Colours::black);
g.drawRect(0, 0, getWidth(), getHeight(), 1);
}

+ 525
- 475
ports/cabbage/source/CabbagePropertiesDialog.h
File diff suppressed because it is too large
View File


+ 902
- 808
ports/cabbage/source/CabbageTable.cpp
File diff suppressed because it is too large
View File


+ 146
- 138
ports/cabbage/source/CabbageTable.h View File

@@ -3,6 +3,7 @@
#include "JuceHeader.h"
#include "CabbageUtils.h"
#include "./Plugin/CabbagePluginProcessor.h"
#define HANDLESIZE 8
#define LINEAR 0
@@ -18,35 +19,35 @@
====================================================================================
*/
class CabbageEnvelopeHandleComponent : public Component,
public ChangeBroadcaster
public ChangeBroadcaster
{
public:
CabbageEnvelopeHandleComponent(int index, Colour colour, bool fixed);
~CabbageEnvelopeHandleComponent();
CabbageEnvelopeHandleComponent(int index, Colour colour, bool fixed);
~CabbageEnvelopeHandleComponent();
class Table* getParentComponent();
void paint (Graphics& g);
void removeThisHandle();
void mouseEnter (const MouseEvent& e);
void mouseDown (const MouseEvent& e);
void mouseDrag (const MouseEvent& e);
void mouseUp (const MouseEvent& e);
int index;
int height, width;
int x,y;
class Table* getParentComponent();
void paint (Graphics& g);
void removeThisHandle();
void mouseEnter (const MouseEvent& e);
void mouseDown (const MouseEvent& e);
void mouseDrag (const MouseEvent& e);
void mouseUp (const MouseEvent& e);
int index;
int height, width;
int x,y;
CabbageEnvelopeHandleComponent* getPreviousHandle();
CabbageEnvelopeHandleComponent* getNextHandle();
CabbageEnvelopeHandleComponent* getPreviousHandle();
CabbageEnvelopeHandleComponent* getNextHandle();
String changeMessage;
String changeMessage;
private:
Colour colour;
bool fixed;
ComponentDragger dragger;
int lastX, lastY;
int offsetX, offsetY;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CabbageEnvelopeHandleComponent);
Colour colour;
bool fixed;
ComponentDragger dragger;
int lastX, lastY;
int offsetX, offsetY;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CabbageEnvelopeHandleComponent);
};
@@ -60,13 +61,13 @@ private:
class TableData
{
public:
Array<double, CriticalSection> amps, x, y;
Array<float, CriticalSection> amps, x, y;
};
class OverviewData
{
public:
Array<double> minAmps, maxAmps, minY, maxY;
Array<double> minAmps, maxAmps, minY, maxY;
};
/*
@@ -77,78 +78,79 @@ public:
====================================================================================
*/
class Table : public Component,
public ChangeBroadcaster,
public ChangeListener
public ChangeBroadcaster,
public ChangeListener
{
public:
Table (String chan, int tblNumber, int tableSize, bool fixedEnv, bool drawHorizontal, bool drawOriginal, Colour colour);
~Table();
void resized();
void setOriginalWidth(int w);
void setGlobalAmpRange (float globalMax, float globalMin, float globalRange);
void createAmpOverviews (Array<double, CriticalSection> csndInputData);
void setDataSource (int zoomValue);
float convertAmpToPixel (float ampValue);
float convertPixelToAmp(float pixelYValue);
void cacheBackgroundImage();
void paint (Graphics& g);
void mouseDown (const MouseEvent& e);
void applyZoom(int newZoom);
void setToEnabled(bool isEnabled);
void setViewWidth(float width);
void setViewStart(float x);
CabbageEnvelopeHandleComponent* addHandle(int x, int y, bool fixedPos, int width, Colour col);
CabbageEnvelopeHandleComponent* getPreviousHandle(CabbageEnvelopeHandleComponent* thisHandle);
CabbageEnvelopeHandleComponent* getNextHandle(CabbageEnvelopeHandleComponent* thisHandle);
int getHandleIndex(CabbageEnvelopeHandleComponent* thisHandle);
void removeHandle (CabbageEnvelopeHandleComponent* thisHandle);
void modifyHandlePos (float j);
void makeTableEditable();
void createHandlesFromTable(int points);
void changeListenerCallback(juce::ChangeBroadcaster *source);
TableData tableData;
float scrubberPosition;
String channel;
int tableNumber, tableSize;
Path envPath;
bool drawOriginalTableData, isCurrentlyOnTop, drawFill,
drawHorizontalSegments, fixedEnvelope, toggleMaxMin;
OwnedArray<CabbageEnvelopeHandleComponent, CriticalSection> handles;
void setYValueOfHandle(int x, int y);
void toggleMinMaxAmp(int x);
float minAmp, maxAmp;
String changeMessage;
String currentfStatement;
float ampRange, zeroAmpPosition;
Colour currColour;
bool isResizing;
bool useAmpRanges;
Point<float> minMaxAmps;
bool editMode;
Table (String chan, int tblNumber, int tableSize, bool fixedEnv, bool drawHorizontal, bool drawOriginal, Colour colour);
~Table();
void resized();
void setOriginalWidth(int w);
void setGlobalAmpRange (float globalMax, float globalMin, float globalRange);
void createAmpOverviews (Array<float, CriticalSection> csndInputData);
void setDataSource (int zoomValue);
float convertAmpToPixel (float ampValue);
float convertPixelToAmp(float pixelYValue);
void cacheBackgroundImage();
void paint (Graphics& g);
void mouseDown (const MouseEvent& e);
void applyZoom(int newZoom);
void setToEnabled(bool isEnabled);
void setViewWidth(float width);
void setViewStart(float x);
CabbageEnvelopeHandleComponent* addHandle(int x, int y, bool fixedPos, int width, Colour col);
CabbageEnvelopeHandleComponent* getPreviousHandle(CabbageEnvelopeHandleComponent* thisHandle);
CabbageEnvelopeHandleComponent* getNextHandle(CabbageEnvelopeHandleComponent* thisHandle);
int getHandleIndex(CabbageEnvelopeHandleComponent* thisHandle);
void removeHandle (CabbageEnvelopeHandleComponent* thisHandle);
void modifyHandlePos (float j);
void makeTableEditable();
void createHandlesFromTable(int points);
void changeListenerCallback(juce::ChangeBroadcaster *source);
TableData tableData;
float scrubberPosition;
String channel;
int tableNumber, tableSize;
Path envPath;
bool drawOriginalTableData, isCurrentlyOnTop, drawFill,
drawHorizontalSegments, fixedEnvelope, toggleMaxMin;
OwnedArray<CabbageEnvelopeHandleComponent, CriticalSection> handles;
void setYValueOfHandle(int x, int y);
void toggleMinMaxAmp(int x);
float minAmp, maxAmp;
String changeMessage;
String currentfStatement;
float ampRange, zeroAmpPosition;
Colour currColour;
bool isResizing;
bool useAmpRanges;
Point<float> minMaxAmps;
bool editMode;
int gen;
StringArray fStatement;
private:
Viewport* viewport;
Viewport* viewport;
Image img;
int gen;
int handleWidth;
float tableTop, tableBottom, tableLeft, tableHeight;
float zoom;
float viewX, viewWidth;
Image img;
int handleWidth;
float tableTop, tableBottom, tableLeft, tableHeight;
float zoom;
float viewX, viewWidth;
OverviewData overview;
Colour activeColour;
int origWidth;
bool useOverview;
float maxZoomForOverview, numPixelsPerIndex;
float minWaveHeight;
OverviewData overview;
Colour activeColour;
int origWidth;
bool useOverview;
float maxZoomForOverview, numPixelsPerIndex;
float minWaveHeight;
CabbageEnvelopeHandleComponent* draggingHandle;
CabbageEnvelopeHandleComponent* draggingHandle;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Table);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Table);
};
/*
@@ -164,47 +166,53 @@ private:
class CabbageTableManager : public Component
{
public:
CabbageTableManager(int tableSize);
~CabbageTableManager();
void resized();
void setOriginalWidth(float width);
void paint(Graphics& g);
float convertAmpToPixel (float ampValue);
void addTable (String name, String channel, int tableNumber,
int tableSize,
bool fixedEnv,
bool drawHoriz,
bool drawOrig,
bool toggleMaxMin,
bool drawFill,
int resizeMode,
Point<float> maxMin,
Colour colour,
bool readOnly,
ChangeListener* listener);
void fillTable (int tableID, Array<double, CriticalSection> csndInputData);
void tableToTop (int tableOnTop);
void mouseDown (const MouseEvent& e);
void mouseDrag(const MouseEvent& e);
Table* getTable(int index);
int getNumberOfTables(){
return tables.size();
}
CabbageTableManager(int tableSize);
~CabbageTableManager();
void resized();
void setOriginalWidth(float width);
void paint(Graphics& g);
float convertAmpToPixel (float ampValue);
void addTable (String name, String channel, int tableNumber,
int tableSize,
bool fixedEnv,
bool drawHoriz,
bool drawOrig,
bool toggleMaxMin,
bool drawFill,
int resizeMode,
Point<float> maxMin,
Colour colour,
bool readOnly,
bool stackMode,
int numberOfTables,
ChangeListener* listener);
void fillTable (int tableID, Array<float, CriticalSection> csndInputData);
void setEvtCode(int ID, StringArray fdata);
void tableToTop (int tableOnTop);
void mouseDown (const MouseEvent& e);
void mouseMove (const MouseEvent& e);
void mouseDrag(const MouseEvent& e);
Table* getTable(int index);
int getNumberOfTables()
{
return tables.size();
}
private:
OwnedArray<Table, CriticalSection> tables;
float originalWidth;
float alpha;
bool readOnly;
int zoom, maxZoom;
float globalMaxAmp, globalMinAmp, globalAmpRange;
float maxNumPixelsPerIndex;
int currentTableIndex;
int tableSize;
float tableTop, tableBottom, tableHeight;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CabbageTableManager);
OwnedArray<Table, CriticalSection> tables;
float originalWidth;
float alpha;
bool toggleMode;
bool readOnly;
int zoom, maxZoom;
float globalMaxAmp, globalMinAmp, globalAmpRange;
float maxNumPixelsPerIndex;
int currentTableIndex;
int tableSize;
float tableTop, tableBottom, tableHeight;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CabbageTableManager);
};
@@ -219,23 +227,23 @@ private:
====================================================================================
*/
class CabbageTableViewer : public Viewport
//public Component
//public Component
{
public:
CabbageTableViewer();
~CabbageTableViewer();
void resized();
void addTable (String name, int tableSize, Colour colour, float alpha);
void fillTable (int tableIndex, Array<float> csndInputData);
void tableToTop (int tableIndex);
void setScrubberPosition(int tableIndex, float position);
CabbageTableViewer();
~CabbageTableViewer();
void resized();
void addTable (String name, int tableSize, Colour colour, float alpha);
void fillTable (int tableIndex, Array<float> csndInputData);
void tableToTop (int tableIndex);
void setScrubberPosition(int tableIndex, float position);
private:
ScopedPointer<CabbageTableManager> tableManager;
//OwnedArray<Table> tables;
//float tableOpacity;
ScopedPointer<CabbageTableManager> tableManager;
//OwnedArray<Table> tables;
//float tableOpacity;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CabbageTableViewer);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CabbageTableViewer);
};


+ 599
- 626
ports/cabbage/source/CabbageUtils.h
File diff suppressed because it is too large
View File


+ 587
- 524
ports/cabbage/source/ComponentLayoutEditor.cpp
File diff suppressed because it is too large
View File


+ 111
- 108
ports/cabbage/source/ComponentLayoutEditor.h View File

@@ -1,6 +1,6 @@
/*
* ComponentLayoutEditor.h
*
*
* Original written by Haydxn
* Modified by Jordan Hochenbaum on 10/25/10.
* http://www.rawmaterialsoftware.com/viewtopic.php?f=6&t=2635
@@ -23,125 +23,128 @@ extern ApplicationProperties* appProperties;
class SelectedComponents : public SelectedItemSet<ChildAlias*>
{
public:
void itemSelected (ChildAlias* item);
void itemDeselected (ChildAlias* item);
void itemSelected (ChildAlias* item);
void itemDeselected (ChildAlias* item);
};
//=============================================================================
class ComponentLayoutEditor : public Component,
public LassoSource <ChildAlias*>,
public ChangeBroadcaster
public LassoSource <ChildAlias*>,
public ChangeBroadcaster
{
public:
enum ColourIds
{
aliasIdleColour,
aliasHoverColour
};
ComponentLayoutEditor ();
~ComponentLayoutEditor ();
void findLassoItemsInArea (Array <ChildAlias*>& results, const Rectangle<int>& area);
Rectangle<int> getLassoRect(SelectedItemSet <ChildAlias*>);
public:
SelectedItemSet <ChildAlias*>& getLassoSelection();
void resized ();
void paint (Graphics& g);
void setTargetComponent (Component* target);
void bindWithTarget ();
void updateFrames ();
void selectDuplicatedComponents(Array<Rectangle <int> > controls);
Point<int> currentMouseCoors;
String currentEvent;
void mouseDown (const MouseEvent& e);
void mouseDrag (const MouseEvent& e);
void mouseUp(const MouseEvent& e);
LassoComponent <ChildAlias*> lassoComp;
SelectedComponents selectedFilters;
Array<Rectangle < int > > selectedCompsOrigCoordinates;
Array<Rectangle < int > > selectedCompsNewCoordinates;
void enablementChanged ();
const Component* getTarget ();
void resetAllBorders();
private:
virtual ChildAlias* createAlias (Component* child, String type, int index);
SafePointer<Component> target;
OwnedArray<ChildAlias> frames;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ComponentLayoutEditor);
enum ColourIds
{
aliasIdleColour,
aliasHoverColour
};
ComponentLayoutEditor ();
~ComponentLayoutEditor ();
void findLassoItemsInArea (Array <ChildAlias*>& results, const juce::Rectangle<int>& area);
juce::Rectangle<int> getLassoRect(SelectedItemSet <ChildAlias*>);
SelectedItemSet <ChildAlias*>& getLassoSelection();
void resized ();
void paint (Graphics& g);
void setTargetComponent (Component* target);
void bindWithTarget ();
void updateFrames ();
void selectDuplicatedComponents(Array<juce::Rectangle <int> > controls);
Point<int> currentMouseCoors;
String currentEvent;
void mouseDown (const MouseEvent& e);
void mouseDrag (const MouseEvent& e);
void mouseUp(const MouseEvent& e);
LassoComponent <ChildAlias*> lassoComp;
SelectedComponents selectedFilters;
Array<int> selectedLineNumbers;
Array<juce::Rectangle < int > > selectedCompsOrigCoordinates;
Array<juce::Rectangle < int > > selectedCompsNewCoordinates;
void enablementChanged ();
const Component* getTarget ();
void resetAllBorders();
Array<juce::Rectangle <int> > boundsForDuplicatedCtrls;
private:
virtual ChildAlias* createAlias (Component* child, String type, int index);
SafePointer<Component> target;
OwnedArray<ChildAlias> frames;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ComponentLayoutEditor);
};
//=============================================================================
class ChildAlias : public Component,
public CabbageUtils,
public KeyListener
public CabbageUtils,
public KeyListener
{
public:
ChildAlias (Component* targetChild, String type, int index);
~ChildAlias ();
void resized ();
void paint (Graphics& g);
const Component* getTargetChild ();
const Component* getTarget();
CabbageMainPanel* getMainPanel();
ComponentLayoutEditor* getLayoutEditor()
{
public:
ChildAlias (Component* targetChild, String type, int index);
~ChildAlias ();
void resized ();
void paint (Graphics& g);
const Component* getTargetChild ();
const Component* getTarget();
CabbageMainPanel* getMainPanel();
ComponentLayoutEditor* getLayoutEditor(){
ComponentLayoutEditor* c = dynamic_cast <ComponentLayoutEditor*> (getParentComponent());
if(c)
return c;
else
return nullptr;
}
bool keyPressed(const juce::KeyPress &key ,Component *);
void updateFromTarget ();
void applyToTarget (String triggeredFrom);
virtual void userChangedBounds ();
virtual void userStartedChangingBounds ();
virtual void userStoppedChangingBounds ();
bool boundsChangedSinceStart ();
void restrictBounds(int &x, int &y);
void mouseEnter (const MouseEvent& e);
void mouseExit (const MouseEvent& e);
void mouseDown (const MouseEvent& e);
void mouseUp (const MouseEvent& e);
void mouseDrag (const MouseEvent& e);
void mouseDoubleClick(const MouseEvent &event);
bool interest, lockMovement;
private:
int index;
Array<Rectangle<int> > origBounds;
int dragX, dragY;
String type;
CriticalSection bounds;
ScopedPointer<ComponentBoundsConstrainer> constrainer;
ComponentDragger dragger;
SafePointer<Component> target;
bool userAdjusting;
Rectangle<int> startBounds;
ScopedPointer<ComponentBoundsConstrainer> resizeContainer; //added resizeContainer to limit resizing sizes
ScopedPointer<ResizableBorderComponent> resizer;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChildAlias);
};
ComponentLayoutEditor* c = dynamic_cast <ComponentLayoutEditor*> (getParentComponent());
if(c)
return c;
else
return nullptr;
}
bool keyPressed(const juce::KeyPress &key ,Component *);
void updateFromTarget ();
void applyToTarget (String triggeredFrom);
virtual void userChangedBounds ();
virtual void userStartedChangingBounds ();
virtual void userStoppedChangingBounds ();
bool boundsChangedSinceStart ();
void restrictBounds(int &x, int &y);
void mouseEnter (const MouseEvent& e);
void mouseExit (const MouseEvent& e);
void mouseDown (const MouseEvent& e);
void mouseUp (const MouseEvent& e);
void mouseDrag (const MouseEvent& e);
void mouseDoubleClick(const MouseEvent &event);
bool interest, lockMovement;
private:
int index;
Array<juce::Rectangle<int> > origBounds;
int dragX, dragY;
String type;
CriticalSection bounds;
ScopedPointer<ComponentBoundsConstrainer> constrainer;
ComponentDragger dragger;
SafePointer<Component> target;
bool userAdjusting;
juce::Rectangle<int> startBounds;
ScopedPointer<ComponentBoundsConstrainer> resizeContainer; //added resizeContainer to limit resizing sizes
ScopedPointer<ResizableBorderComponent> resizer;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChildAlias);
};
#endif//_COMPONENTLAYOUTEDITOR_H_

+ 172
- 160
ports/cabbage/source/DirectoryContentsComponent.cpp View File

@@ -4,7 +4,7 @@
Cabbage is free software; you can redistribute it
and/or modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
version 2.1 of the License, or (at your option) any later version.
Cabbage is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -21,215 +21,227 @@
//==============================================================================
DirectoryContentsComponent::DirectoryContentsComponent(String dir, String files):
fileTypes(files),
rootDir(dir),
thread ("audio file preview"),
fileTreeComp (0),
editor(0),
ftableCounter(1),
lookAndFeel(0),
fileTypes(files),
rootDir(dir),
thread ("audio file preview"),
fileTreeComp (0),
editor(0),
ftableCounter(1),
lookAndFeel(0),
//filter("*.wav;*.ogg;*.aiff", "*.*", "Audio Files"),
filter(files, "*.*", ""),
directoryList(&filter, thread)
filter(files, "*.*", ""),
directoryList(&filter, thread)
{
;
//directoryList.addChangeListener()
//create and set Cabbage look and feel
//directoryList.addChangeListener()
//create and set Cabbage look and feel
lookAndFeel=new CabbageLookAndFeel();
basicLookAndFeel = new CabbageLookAndFeelBasic();
setLookAndFeel(lookAndFeel);
//directory list
fileTreeComp = new FileTreeComponent(directoryList);
fileTreeComp->addListener(this);
//if file dir is valid set it, otherwise root is base
//custom FunctionTable class
tablesList.add(new FunctionTableList());
tablesList[0]->addActionListener(this);
//table list class, uses above object as it's model
tables.add(new TableListBox("list", tablesList[0]));
tables[0]->setLookAndFeel(lookAndFeel);
tables[0]->setMultipleSelectionEnabled(true);
tables[0]->setColour(TableListBox::backgroundColourId, Colours::black);
tables[0]->setColour(TableListBox::outlineColourId, Colours::black);
tables[0]->setOutlineThickness (1);
//addAndMakeVisible(tables[0]);
functionRowData.add(new StringArray());
tabComp = new TabbedComponent(TabbedButtonBar::TabsAtTop);
tabComp->setLookAndFeel(basicLookAndFeel);
tabComp->setTabBarDepth(25);
//tabComp->setColour(TabbedButtonBar::tabTextColourId, Colours::white);
tabComp->setColour(TabbedButtonBar::tabOutlineColourId, Colours::black);
tabComp->addTab("Bank 1", Colours::white, tables[0], false);
tabComp->setOutline(0);
tabComp->repaint();
addAndMakeVisible(tabComp);
tables[0]->getHeader().addColumn ("Function Tables", 1, 400, 35, 400, TableHeaderComponent::defaultFlags);
tables[0]->getHeader().setSize(tables[0]->getWidth(), 25);
//file directory setups....
if(File(rootDir).isDirectory())
directoryList.setDirectory(File(rootDir), true, true);
else
directoryList.setDirectory (File::getSpecialLocation (File::userHomeDirectory), true, true);
thread.startThread (3);
basicLookAndFeel = new CabbageLookAndFeelBasic();
setLookAndFeel(lookAndFeel);
//directory list
fileTreeComp = new FileTreeComponent(directoryList);
fileTreeComp->addListener(this);
//if file dir is valid set it, otherwise root is base
//custom FunctionTable class
tablesList.add(new FunctionTableList());
tablesList[0]->addActionListener(this);
//table list class, uses above object as it's model
tables.add(new TableListBox("list", tablesList[0]));
tables[0]->setLookAndFeel(lookAndFeel);
tables[0]->setMultipleSelectionEnabled(true);
tables[0]->setColour(TableListBox::backgroundColourId, Colours::black);
tables[0]->setColour(TableListBox::outlineColourId, Colours::black);
tables[0]->setOutlineThickness (1);
//addAndMakeVisible(tables[0]);
functionRowData.add(new StringArray());
tabComp = new TabbedComponent(TabbedButtonBar::TabsAtTop);
tabComp->setLookAndFeel(basicLookAndFeel);
tabComp->setTabBarDepth(25);
//tabComp->setColour(TabbedButtonBar::tabTextColourId, Colours::white);
tabComp->setColour(TabbedButtonBar::tabOutlineColourId, Colours::black);
tabComp->addTab("Bank 1", Colours::white, tables[0], false);
tabComp->setOutline(0);
tabComp->repaint();
addAndMakeVisible(tabComp);
tables[0]->getHeader().addColumn ("Function Tables", 1, 400, 35, 400, TableHeaderComponent::defaultFlags);
tables[0]->getHeader().setSize(tables[0]->getWidth(), 25);
//file directory setups....
if(File(rootDir).isDirectory())
directoryList.setDirectory(File(rootDir), true, true);
else
directoryList.setDirectory (File::getSpecialLocation (File::userHomeDirectory), true, true);
thread.startThread (3);
fileTreeComp->setColour(0x1000501, Colours::green);//linesColourId
fileTreeComp->setColour(DirectoryContentsDisplayComponent::textColourId, Colours::white);
fileTreeComp->setColour(ListBox::outlineColourId, Colours::red);
fileTreeComp->addListener (this);
addBankButton = new TextButton("Add Bank");
addBankButton->addListener(this);
addBankButton->setLookAndFeel(basicLookAndFeel);
addBankButton->setColour(TextButton::buttonColourId, Colours::cornflowerblue.withAlpha(.4f));
addBankButton->setColour(TextButton::textColourOffId, Colours::white);
addBankButton->setColour(TextButton::textColourOnId, Colours::white);
updateTablesButton = new TextButton("Update Tables");
updateTablesButton->addListener(this);
updateTablesButton->setLookAndFeel(basicLookAndFeel);
updateTablesButton->setColour(TextButton::buttonColourId, Colours::cornflowerblue.withAlpha(.4f));
updateTablesButton->setColour(TextButton::textColourOffId, Colours::white);
updateTablesButton->setColour(TextButton::textColourOnId, Colours::white);
autoUpdate = new ToggleButton("Auto-update");
autoUpdate->getProperties().set("isRect", true);
autoUpdate->getProperties().set("colour", Colours::lime.toString());
autoUpdate->getProperties().set("fontcolour", Colours::white.toString());
//add everything to screen
addAndMakeVisible(autoUpdate);
addAndMakeVisible (fileTreeComp);
addAndMakeVisible(updateTablesButton);
addAndMakeVisible(addBankButton);
setSize (600, 500);
fileTreeComp->setColour(ListBox::outlineColourId, Colours::red);
fileTreeComp->addListener (this);
addBankButton = new TextButton("Add Bank");
addBankButton->addListener(this);
addBankButton->setLookAndFeel(basicLookAndFeel);
addBankButton->setColour(TextButton::buttonColourId, Colours::cornflowerblue.withAlpha(.4f));
addBankButton->setColour(TextButton::textColourOffId, Colours::white);
addBankButton->setColour(TextButton::textColourOnId, Colours::white);
updateTablesButton = new TextButton("Update Tables");
updateTablesButton->addListener(this);
updateTablesButton->setLookAndFeel(basicLookAndFeel);
updateTablesButton->setColour(TextButton::buttonColourId, Colours::cornflowerblue.withAlpha(.4f));
updateTablesButton->setColour(TextButton::textColourOffId, Colours::white);
updateTablesButton->setColour(TextButton::textColourOnId, Colours::white);
autoUpdate = new ToggleButton("Auto-update");
autoUpdate->getProperties().set("isRect", true);
autoUpdate->getProperties().set("colour", Colours::lime.toString());
autoUpdate->getProperties().set("fontcolour", Colours::white.toString());
//add everything to screen
addAndMakeVisible(autoUpdate);
addAndMakeVisible (fileTreeComp);
addAndMakeVisible(updateTablesButton);
addAndMakeVisible(addBankButton);
setSize (600, 500);
}
//====================================================================================
DirectoryContentsComponent::~DirectoryContentsComponent()
{
thread.stopThread(10);
thread.stopThread(10);
}
//====================================================================================
void DirectoryContentsComponent::paint (Graphics& g)
{
g.setColour(CabbageUtils::getBackgroundSkin());
g.fillRoundedRectangle(0, 0, getWidth(), getHeight(), 7);
g.setColour(CabbageUtils::getBackgroundSkin());
g.fillRoundedRectangle(0, 0, getWidth(), getHeight(), 7);
}
//====================================================================================
void DirectoryContentsComponent::resized()
{
//resize evcerything
fileTreeComp->setBounds (5, 5, (getWidth()/2)-5, getHeight()-45);
tabComp->setBounds (getWidth()/2+5, 5, (getWidth()/2)-10, getHeight()-45);
addBankButton->setBounds(5, getHeight()-35, 90, 25);
updateTablesButton->setBounds(100, getHeight()-35, 110, 25);
autoUpdate->setBounds(220, getHeight()-35, 150, 25);
//resize evcerything
fileTreeComp->setBounds (5, 5, (getWidth()/2)-5, getHeight()-45);
tabComp->setBounds (getWidth()/2+5, 5, (getWidth()/2)-10, getHeight()-45);
addBankButton->setBounds(5, getHeight()-35, 90, 25);
updateTablesButton->setBounds(100, getHeight()-35, 110, 25);
autoUpdate->setBounds(220, getHeight()-35, 150, 25);
}
//====================================================================================
//populate table rows with new strings and add new items to listable
void DirectoryContentsComponent::fileClicked (const File& file, const MouseEvent& e)
{
}
//====================================================================================
//this will listen for messages from our FunctionTableList object, and behave accordingly.
void DirectoryContentsComponent::actionListenerCallback(const juce::String& string){
if(string=="delete selected"){
if(tables[tabComp->getCurrentTabIndex()]->getNumSelectedRows()>0){
SparseSet<int> sparseSet = tables[tabComp->getCurrentTabIndex()]->getSelectedRows();
for(int i=sparseSet.size();i>=0;i--){
functionRowData[tabComp->getCurrentTabIndex()]->remove(sparseSet[i]);
}
tables[tabComp->getCurrentTabIndex()]->deselectAllRows();
tablesList[tabComp->getCurrentTabIndex()]->addOrModifyRows(tabComp->getCurrentTabIndex(), *functionRowData[tabComp->getCurrentTabIndex()]);
tables[tabComp->getCurrentTabIndex()]->updateContent();
tables[tabComp->getCurrentTabIndex()]->repaint();
}
}
else if(string=="deselect")
tables[tabComp->getCurrentTabIndex()]->deselectAllRows();
//this will listen for messages from our FunctionTableList object, and behave accordingly.
void DirectoryContentsComponent::actionListenerCallback(const juce::String& string)
{
if(string=="delete selected")
{
if(tables[tabComp->getCurrentTabIndex()]->getNumSelectedRows()>0)
{
SparseSet<int> sparseSet = tables[tabComp->getCurrentTabIndex()]->getSelectedRows();
for(int i=sparseSet.size(); i>=0; i--)
{
functionRowData[tabComp->getCurrentTabIndex()]->remove(sparseSet[i]);
}
tables[tabComp->getCurrentTabIndex()]->deselectAllRows();
tablesList[tabComp->getCurrentTabIndex()]->addOrModifyRows(tabComp->getCurrentTabIndex(), *functionRowData[tabComp->getCurrentTabIndex()]);
tables[tabComp->getCurrentTabIndex()]->updateContent();
tables[tabComp->getCurrentTabIndex()]->repaint();
}
}
else if(string=="deselect")
tables[tabComp->getCurrentTabIndex()]->deselectAllRows();
}
//====================================================================================
//button clicks
void DirectoryContentsComponent::buttonClicked(Button* button)
{
//each time the add bank button is clicked add a new object to tablesList, and tables arrays, then show them on the
//tabbed component..
if(button->getName()=="Add Bank"){
functionRowData.add(new StringArray());
tablesList.add(new FunctionTableList());
tablesList[tablesList.size()-1]->addActionListener(this);
tables.add(new TableListBox("list", tablesList[tablesList.size()-1]));
tables[tables.size()-1]->setLookAndFeel(lookAndFeel);
tables[tables.size()-1]->setMultipleSelectionEnabled(true);
tables[tables.size()-1]->setColour(TableListBox::textColourId, Colours::white);
tables[tables.size()-1]->setColour(TableListBox::backgroundColourId, Colours::black);
tables[tables.size()-1]->getHeader().addColumn ("Function Tables", 1, 400, 50, 400, TableHeaderComponent::defaultFlags);
tabComp->addTab("Bank "+String(tabComp->getNumTabs()+1), Colours::white, tables[tables.size()-1], false);
tabComp->setCurrentTabIndex(tables.size()-1);
}
if(button->getName()=="Update Tables"){
sendActionMessage("updatingDirectoryTables");
}
//each time the add bank button is clicked add a new object to tablesList, and tables arrays, then show them on the
//tabbed component..
if(button->getName()=="Add Bank")
{
functionRowData.add(new StringArray());
tablesList.add(new FunctionTableList());
tablesList[tablesList.size()-1]->addActionListener(this);
tables.add(new TableListBox("list", tablesList[tablesList.size()-1]));
tables[tables.size()-1]->setLookAndFeel(lookAndFeel);
tables[tables.size()-1]->setMultipleSelectionEnabled(true);
tables[tables.size()-1]->setColour(TableListBox::textColourId, Colours::white);
tables[tables.size()-1]->setColour(TableListBox::backgroundColourId, Colours::black);
tables[tables.size()-1]->getHeader().addColumn ("Function Tables", 1, 400, 50, 400, TableHeaderComponent::defaultFlags);
tabComp->addTab("Bank "+String(tabComp->getNumTabs()+1), Colours::white, tables[tables.size()-1], false);
tabComp->setCurrentTabIndex(tables.size()-1);
}
if(button->getName()=="Update Tables")
{
sendActionMessage("updatingDirectoryTables");
}
}
//====================================================================================
void DirectoryContentsComponent::selectionChanged()
{
if(fileTreeComp->getSelectedFile().existsAsFile()){
updateSelection(fileTreeComp->getSelectedFile());
if(autoUpdate->getToggleState())
sendActionMessage("updatingTables");
}
{
if(fileTreeComp->getSelectedFile().existsAsFile())
{
updateSelection(fileTreeComp->getSelectedFile());
if(autoUpdate->getToggleState())
sendActionMessage("updatingTables");
}
}
//====================================================================================
const StringArray DirectoryContentsComponent::getFunctionTables()
{
StringArray tables;
StringArray tables;
//only retrieve the current selected bank
for(int y=0;y<functionRowData[tabComp->getCurrentTabIndex()]->size();y++){
tables.add("f "+String((tabComp->getCurrentTabIndex()+1)*50+y)+" 0 0 1 \""+functionRowData[tabComp->getCurrentTabIndex()]->getReference(y)+"\" 0 4 1");
}
for(int y=0; y<functionRowData[tabComp->getCurrentTabIndex()]->size(); y++)
{
tables.add("f "+String((tabComp->getCurrentTabIndex()+1)*50+y)+" 0 0 1 \""+functionRowData[tabComp->getCurrentTabIndex()]->getReference(y)+"\" 0 4 1");
}
return tables;
return tables;
}
//====================================================================================
void DirectoryContentsComponent::updateSelection(const File& file){
//update the number of rows in our listbox passing
if(tables[tabComp->getCurrentTabIndex()]->getNumSelectedRows()>0){
SparseSet<int> sparseSet = tables[tabComp->getCurrentTabIndex()]->getSelectedRows();
for(int i=0;i<sparseSet.size();i++){
functionRowData[tabComp->getCurrentTabIndex()]->getReference(sparseSet[i])= file.getFullPathName();
tablesList[tabComp->getCurrentTabIndex()]->addOrModifyRows(tabComp->getCurrentTabIndex(), *functionRowData[tabComp->getCurrentTabIndex()]);
tables[tabComp->getCurrentTabIndex()]->repaintRow(sparseSet[i]);
tables[tabComp->getCurrentTabIndex()]->updateContent();
tables[tabComp->getCurrentTabIndex()]->repaint();
}
}
else{
functionRowData[tabComp->getCurrentTabIndex()]->add(file.getFullPathName());
tablesList[tabComp->getCurrentTabIndex()]->addOrModifyRows(tabComp->getCurrentTabIndex(), *functionRowData[tabComp->getCurrentTabIndex()]);
tables[tabComp->getCurrentTabIndex()]->updateContent();
}
void DirectoryContentsComponent::updateSelection(const File& file)
{
//update the number of rows in our listbox passing
if(tables[tabComp->getCurrentTabIndex()]->getNumSelectedRows()>0)
{
SparseSet<int> sparseSet = tables[tabComp->getCurrentTabIndex()]->getSelectedRows();
for(int i=0; i<sparseSet.size(); i++)
{
functionRowData[tabComp->getCurrentTabIndex()]->getReference(sparseSet[i])= file.getFullPathName();
tablesList[tabComp->getCurrentTabIndex()]->addOrModifyRows(tabComp->getCurrentTabIndex(), *functionRowData[tabComp->getCurrentTabIndex()]);
tables[tabComp->getCurrentTabIndex()]->repaintRow(sparseSet[i]);
tables[tabComp->getCurrentTabIndex()]->updateContent();
tables[tabComp->getCurrentTabIndex()]->repaint();
}
}
else
{
functionRowData[tabComp->getCurrentTabIndex()]->add(file.getFullPathName());
tablesList[tabComp->getCurrentTabIndex()]->addOrModifyRows(tabComp->getCurrentTabIndex(), *functionRowData[tabComp->getCurrentTabIndex()]);
tables[tabComp->getCurrentTabIndex()]->updateContent();
}
}
//====================================================================================

+ 188
- 172
ports/cabbage/source/DirectoryContentsComponent.h View File

@@ -4,7 +4,7 @@
Cabbage is free software; you can redistribute it
and/or modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
version 2.1 of the License, or (at your option) any later version.
Cabbage is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -27,152 +27,166 @@
//==============================================================================
/* one of these is fitted inside each cell of the table. It contains a text editor
* for the functoin tables number, and a string displaying the file name */
//==============================================================================
//==============================================================================
class listBoxItem : public Component
{
String text;
Colour highlightColour;
int ftableNumber;
ScopedPointer<LookAndFeel_V1> oldSchool;
ScopedPointer<TextEditor> textEditor;
String text;
Colour highlightColour;
int ftableNumber;
ScopedPointer<LookAndFeel_V1> oldSchool;
ScopedPointer<TextEditor> textEditor;
public:
listBoxItem():highlightColour(Colours::white), isHighlighted(false){
oldSchool = new LookAndFeel_V1();
textEditor = new TextEditor();
setInterceptsMouseClicks(false, true);
textEditor->setLookAndFeel(oldSchool);
addAndMakeVisible(textEditor);
setSize(getWidth(), 50);
}
~listBoxItem(){ }
//paint out
void paint(Graphics &g){
g.fillAll(Colours::black.withAlpha(.5f));
g.setColour(highlightColour);
g.drawRect(1, 1, getWidth()-1, getHeight()-1, 2);
g.setColour(Colours::whitesmoke);
g.drawText (text, 55, 0, getWidth() - 4, getHeight(), Justification::centredLeft, true);
}
void resized(){
textEditor->setBounds(3, 3, 40, getHeight()-5);
}
void setText(int _ftableNumber, String _text){
text = _text;
textEditor->setText(String(_ftableNumber));
}
bool isHighlighted;
listBoxItem():highlightColour(Colours::white), isHighlighted(false)
{
oldSchool = new LookAndFeel_V1();
textEditor = new TextEditor();
setInterceptsMouseClicks(false, true);
textEditor->setLookAndFeel(oldSchool);
addAndMakeVisible(textEditor);
setSize(getWidth(), 50);
}
~listBoxItem() { }
//paint out
void paint(Graphics &g)
{
g.fillAll(Colours::black.withAlpha(.5f));
g.setColour(highlightColour);
g.drawRect(1, 1, getWidth()-1, getHeight()-1, 2);
g.setColour(Colours::whitesmoke);
g.drawText (text, 55, 0, getWidth() - 4, getHeight(), Justification::centredLeft, true);
}
void resized()
{
textEditor->setBounds(3, 3, 40, getHeight()-5);
}
void setText(int _ftableNumber, String _text)
{
text = _text;
textEditor->setText(String(_ftableNumber));
}
bool isHighlighted;
};
//==============================================================================
/* this is the table list box model, it' gets passed to our TableListBox object
/* this is the table list box model, it' gets passed to our TableListBox object
this class can send action messages to MainContentComponent whenever something
happens to one of its cells...*/
//==============================================================================
//==============================================================================
class FunctionTableList : public TableListBoxModel,
public ActionBroadcaster
public ActionBroadcaster
{
public:
FunctionTableList():font(14.f), rowData(), numHighlighted(0){
numRows=0;
ftableCounter=0;
}
~FunctionTableList(){
listBoxItems.clear();
}
void paintRowBackground (Graphics& g, int rowNumber, int width, int height, bool rowIsSelected)
{
g.fillAll (CabbageUtils::getBackgroundSkin());
g.setFont (font);
g.setColour(Colours::white);
//g.drawText (rowData[rowNumber], 2, 0, width - 4, height, Justification::centredLeft, true);
FunctionTableList():font(14.f), rowData(), numHighlighted(0)
{
numRows=0;
ftableCounter=0;
}
~FunctionTableList()
{
listBoxItems.clear();
}
void paintRowBackground (Graphics& g, int rowNumber, int width, int height, bool rowIsSelected)
{
g.fillAll (CabbageUtils::getBackgroundSkin());
g.setFont (font);
g.setColour(Colours::white);
//g.drawText (rowData[rowNumber], 2, 0, width - 4, height, Justification::centredLeft, true);
if (rowIsSelected)
g.fillAll (Colours::cornflowerblue);
}
//add or modify exiting funcoitn table entries
void addOrModifyRows(int _bankNumber, StringArray functionRows){
rowData.clear();
rowData = functionRows;
bankNumber = _bankNumber+1;
ftableCounter = 0;
numRows = rowData.size();
}
// This is overloaded from TableListBoxModel, and must update any custom components that we're using
Component* refreshComponentForCell (int rowNumber, int columnId, bool /*isRowSelected*/,
Component* existingComponentToUpdate)
{
if (columnId == 1) // If it's the main column, we'll return our custom component..
{
listBoxItem* boxItem = (listBoxItem*) existingComponentToUpdate;
// If an existing component is being passed-in for updating, we'll re-use it, but
// if not, we'll have to create one.
if (boxItem == 0){
boxItem = new listBoxItem();
}
boxItem->setText(rowNumber+(bankNumber*50), rowData[rowNumber]);
return boxItem;
}
else
{
// for any other column, just return 0, as we'll be painting these columns directly.
jassert (existingComponentToUpdate == 0);
return 0;
}
}
//determine actions to take place when users click on a cell...
void cellClicked (int rowNumber, int columnId, const MouseEvent &e){
if(e.mods.isRightButtonDown()){
PopupMenu m;
CabbageLookAndFeel cLAK;
m.setLookAndFeel(&cLAK);
m.addItem(1, "Delete selected");
int choice = m.show();
if(choice==1)
sendActionMessage("delete selected");
}
}
void backgroundClicked(){
sendActionMessage("deselect");
}
int getNumRows(){
return numRows;
}
void setNumRows(int _numRows){
//add or modify exiting funcoitn table entries
void addOrModifyRows(int _bankNumber, StringArray functionRows)
{
rowData.clear();
rowData = functionRows;
bankNumber = _bankNumber+1;
ftableCounter = 0;
numRows = rowData.size();
}
// This is overloaded from TableListBoxModel, and must update any custom components that we're using
Component* refreshComponentForCell (int rowNumber, int columnId, bool /*isRowSelected*/,
Component* existingComponentToUpdate)
{
if (columnId == 1) // If it's the main column, we'll return our custom component..
{
listBoxItem* boxItem = (listBoxItem*) existingComponentToUpdate;
// If an existing component is being passed-in for updating, we'll re-use it, but
// if not, we'll have to create one.
if (boxItem == 0)
{
boxItem = new listBoxItem();
}
boxItem->setText(rowNumber+(bankNumber*50), rowData[rowNumber]);
return boxItem;
}
else
{
// for any other column, just return 0, as we'll be painting these columns directly.
jassert (existingComponentToUpdate == 0);
return 0;
}
}
//determine actions to take place when users click on a cell...
void cellClicked (int rowNumber, int columnId, const MouseEvent &e)
{
if(e.mods.isRightButtonDown())
{
PopupMenu m;
CabbageLookAndFeel cLAK;
m.setLookAndFeel(&cLAK);
m.addItem(1, "Delete selected");
int choice = 0;//m.show();
if(choice==1)
sendActionMessage("delete selected");
}
}
void backgroundClicked()
{
sendActionMessage("deselect");
}
int getNumRows()
{
return numRows;
}
void setNumRows(int _numRows)
{
numRows = _numRows;
}
void paintCell(juce::Graphics& g, int, int, int, int, bool){
g.fillAll(Colours::pink);
}
void paintCell(juce::Graphics& g, int, int, int, int, bool)
{
g.fillAll(Colours::pink);
}
private:
Font font;
StringArray highlightedItems;
int numRows;
int ftableCounter;
int bankNumber;
int numHighlighted;
StringArray rowData;
OwnedArray<listBoxItem> listBoxItems;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FunctionTableList)
StringArray highlightedItems;
int numRows;
int ftableCounter;
int bankNumber;
int numHighlighted;
StringArray rowData;
OwnedArray<listBoxItem> listBoxItems;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FunctionTableList)
};
//==============================================================================
@@ -183,34 +197,34 @@ private:
//==============================================================================
class DirectoryContentsComponent : public Component,
public FileBrowserListener,
public ButtonListener,
public ActionListener,
public ActionBroadcaster
public FileBrowserListener,
public ButtonListener,
public ActionListener,
public ActionBroadcaster
{
OwnedArray<FunctionTableList> tablesList;
OwnedArray<TableListBox> tables;
OwnedArray<FunctionTableList> tablesList;
OwnedArray<TableListBox> tables;
ScopedPointer<CabbageLookAndFeel> lookAndFeel;
ScopedPointer<CabbageLookAndFeelBasic> basicLookAndFeel;
StretchableLayoutManager horizontalLayout;
ScopedPointer<Viewport> viewPort;
StretchableLayoutManager horizontalLayout;
ScopedPointer<Viewport> viewPort;
ScopedPointer<StretchableLayoutResizerBar> horizontalDividerBar;
ScopedPointer<TabbedComponent> tabComp;
ScopedPointer<TextEditor> editor;
ScopedPointer<TextButton> updateTablesButton;
ScopedPointer<ToggleButton> autoUpdate;
ScopedPointer<TextButton> addBankButton;
StringArray functionTableStrings;
DirectoryContentsList directoryList;
TimeSliceThread thread;
int ftableCounter;
ScopedPointer<FileTreeComponent> fileTreeComp;
WildcardFileFilter filter;
//Array of stireng arrays....
OwnedArray<StringArray> functionRowData;
String fileTypes, rootDir;
StringArray previousScoreEvents;
ScopedPointer<TabbedComponent> tabComp;
ScopedPointer<TextEditor> editor;
ScopedPointer<TextButton> updateTablesButton;
ScopedPointer<ToggleButton> autoUpdate;
ScopedPointer<TextButton> addBankButton;
StringArray functionTableStrings;
DirectoryContentsList directoryList;
TimeSliceThread thread;
int ftableCounter;
ScopedPointer<FileTreeComponent> fileTreeComp;
WildcardFileFilter filter;
//Array of stireng arrays....
OwnedArray<StringArray> functionRowData;
String fileTypes, rootDir;
StringArray previousScoreEvents;
public:
//==============================================================================
DirectoryContentsComponent(String dir, String files);
@@ -218,32 +232,34 @@ public:
bool isFileSuitable(const juce::File&) const
{
return true;
}
{
return true;
}
bool isDirectorySuitable(const juce::File&) const
{
return true;
}
void fileDoubleClicked (const File& file){
Logger::writeToLog("file double clicked");
}
void browserRootChanged (const File&) {
Logger::writeToLog("root changed");
}
void updateSelection(const File& file);
void showFile (const File& file){}
{
return true;
}
void fileDoubleClicked (const File& file)
{
Logger::writeToLog("file double clicked");
}
void browserRootChanged (const File&)
{
Logger::writeToLog("root changed");
}
void updateSelection(const File& file);
void showFile (const File& file) {}
void paint (Graphics&);
void resized();
void buttonClicked(Button* button);
void fileClicked(const File& file, const MouseEvent& e);
void actionListenerCallback(const juce::String& string);
void selectionChanged();
const StringArray getFunctionTables();
void resized();
void buttonClicked(Button* button);
void fileClicked(const File& file, const MouseEvent& e);
void actionListenerCallback(const juce::String& string);
void selectionChanged();
const StringArray getFunctionTables();
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DirectoryContentsComponent)


+ 1201
- 382
ports/cabbage/source/Editor/CodeEditor.cpp
File diff suppressed because it is too large
View File


+ 386
- 55
ports/cabbage/source/Editor/CodeEditor.h View File

@@ -30,68 +30,399 @@
extern ApplicationProperties* appProperties;
extern CabbageTimer* cabbageTimer;

class CsoundCodeEditor : public CodeEditorComponent,
public ActionBroadcaster,
public CodeDocument::Listener
{
public:
CodeDocument::Position positionInCode;
CsoundCodeEditor(String type, CodeDocument &document, CodeTokeniser *codeTokeniser);
class FlatButton;
class HelpComp;
class SearchReplaceComp;

~CsoundCodeEditor();
class CsoundCodeEditorComponenet : public CodeEditorComponent,
public ActionBroadcaster,
public ChangeBroadcaster,
public CodeDocument::Listener
{
public:
CodeDocument::Position positionInCode;
CsoundCodeEditorComponenet(String type, CodeDocument &document, CodeTokeniser *codeTokeniser);
~CsoundCodeEditorComponenet();
bool keyPressed (const KeyPress& key);
void handleTabKey(String direction);
void toggleComments();
void handleDirectionKey() {}

void handleEscapeKey()
{
if(type=="python")
sendActionMessage("make python invisible");
if(type=="csound")
sendActionMessage("make popup invisible");
}

bool keyPressed (const KeyPress& key);
void handleTabKey(String direction);
void toggleComments();
enum DragType
{
notDragging,
draggingSelectionStart,
draggingSelectionEnd
};

DragType dragType;

void handleDirectionKey(){}
void editorHasScrolled();
bool skipBackwardsToPreviousTab();
bool moveCaretLeft (const bool moveInWholeWordSteps, const bool selecting);
bool moveCaretRight (const bool moveInWholeWordSteps, const bool selecting);
bool deleteBackwards (const bool moveInWholeWordSteps);
bool deleteForwards (const bool moveInWholeWordSteps);
void handleReturnKey ();
void addPopupMenuItems (PopupMenu &menuToAddTo, const MouseEvent *mouseClickEvent);
void performPopupMenuAction (int menuItemID);
void modifyInstrumentBreakpoint(bool remove);
String getLineText();
String getTempChannelInstr();
String getSelectedText();
String getInstrumentText();
Rectangle<int> getCaretPoisition();
StringArray getSelectedTextArray();
void addRepoToSettings();
void insertText(String text);
void addToRepository();
StringArray repoEntries;
String getAllText();
void setAllText(String text);
void highlightLine(String line);
void highlightLines(int firstLine, int lastLine);
void codeDocumentTextDeleted(int,int);
void codeDocumentTextInserted(const juce::String &,int);
bool pasteFromClipboard();
void insertNewLine(String text);
void changeListenerCallback(juce::ChangeBroadcaster* source);
void enableColumnEditMode(bool enable);
void setOpcodeStrings(String opcodes)
{
opcodeStrings.addLines(opcodes);
}

void handleEscapeKey(){
if(type=="python")
sendActionMessage("make python invisible");
if(type=="csound")
sendActionMessage("make popup invisible");
}
void handleReturnKey ();
void addPopupMenuItems (PopupMenu &menuToAddTo, const MouseEvent *mouseClickEvent);
void performPopupMenuAction (int menuItemID);
String getLineText();
String getTempChannelInstr();
String getSelectedText();
String getInstrumentText();
Rectangle<int> getCaretPoisition();
StringArray getSelectedTextArray();
void addRepoToSettings();
void insertText(String text);
void addToRepository();
StringArray repoEntries;
String getAllText();
void setAllText(String text);
void highlightLine(String line);
void codeDocumentTextDeleted(int,int);
void codeDocumentTextInserted(const juce::String &,int);
bool textChanged;
void insertNewLine(String text);
void setOpcodeStrings(String opcodes){
opcodeStrings.addLines(opcodes);
}
void insertTextAtCaret (const String &textToInsert);
void updateCaretPosition();
void insertMultiLineTextAtCaret(String text);
String getOpcodeToken(int index)
{
return opcodeTokens[index];
}

bool columnEditMode;
void mouseWheelMove (const MouseEvent&, const MouseWheelDetails&);
void updateCaretPosition();
void insertMultiTextAtCaret(String text);
String getOpcodeToken(int index){
return opcodeTokens[index];
}
private:
int xPos, yPos, prevXpos;
CodeDocument::Position pos1, pos2;
Colour selectedColour;
String type;
StringArray opcodeStrings;
StringArray opcodeTokens;
};
private:
int xPos, yPos, prevXpos;
CodeDocument::Position pos1, pos2;
Colour selectedColour;
int fontSize;
String font;
String type;
StringArray opcodeStrings;
StringArray opcodeTokens;

};

//=================================================================
class CsoundCodeEditor : public Component,
public ChangeListener,
public ActionListener,
public ActionBroadcaster
{
bool showTabButtons;
bool showInstrumentButtons;
int instrWidth;
int searchStartIndex;
bool highlightedWord;
Array<int> breakpointLines;

public:
CsoundCodeEditor(CodeDocument &document, CodeTokeniser *codeTokeniser);
~CsoundCodeEditor();

int saveAllFiles();
void setSavePoint();
void changeListenerCallback(juce::ChangeBroadcaster* source);
String getAllText();
void setAllText(String text);
void highlightLine(String line);
void showTab(String name);
void showInstrs(bool show);
int findText(String text);
String getCurrentSelectedText();
int replaceText(String text, String replaceWith);
void actionListenerCallback(const juce::String&);
void closeCurrentFile();
void setActiveTab(int index);
void saveAuxFile();
OwnedArray<FlatButton> tabButtons;
OwnedArray<FlatButton> instrButtons;
ScopedPointer<HelpComp> helpComp;
ScopedPointer<SearchReplaceComp> searchReplaceComp;
bool textChanged;
OwnedArray<CsoundCodeEditorComponenet> editor;
int currentEditor;
void addNewFile(File newFile);
void paint(Graphics& g);
void resized();
Range<int> getCabbageSectionRange();
OwnedArray<CodeDocument> codeDocuments;
CsoundTokeniser codeToker;
StringArray openFiles;
int documentIndex;
void enableColumnEdit(bool enable);

};


class FlatButton : public Component,
public ChangeBroadcaster
{
public:
FlatButton(String name, int currentTab, String type): name(name),
type(type),
currentTab(currentTab),
isMouseDown(false),
genericColour(Colours::brown)
{
setName(name);
if(name=="Csound code")
active = true;
else
active=false;


}
~FlatButton() {}

void mouseDown(const MouseEvent& event)
{
sendChangeMessage();
Logger::writeToLog("mouseDown");
isMouseDown = true;
repaint();
}

void mouseUp(const MouseEvent& event)
{
Logger::writeToLog("mouseUp");
isMouseDown = false;
repaint();
}

void isActive(bool isActive)
{
active = isActive;
repaint();
}


void paint(Graphics &g)
{
g.fillAll(Colour(20, 20, 20));
if(type=="Native")
{
if(name.contains("code"))
{
if(active)
g.setColour(Colours::cornflowerblue.darker(.4f));
else
g.setColour(Colours::cornflowerblue.darker(.9f));

g.fillRoundedRectangle(getLocalBounds().toFloat(), 5.f);
if(active)
g.setColour(Colours::white);
else
g.setColour(Colours::white.darker(.9f));

g.drawRoundedRectangle(getLocalBounds().toFloat(), 5.f, 2);
g.drawFittedText(name, getLocalBounds(), Justification::centred, 1, 1.f);
}

}
else if(type=="Aux")
{
if(!active)
g.setColour(genericColour.darker(.9f));
else
g.setColour(genericColour.darker(.2f));
g.fillRoundedRectangle(0, 0, getWidth(), getHeight(), 5.f);

if(!active)
g.setColour(Colours::white.darker(.9f));
else
g.setColour(Colours::white);

g.drawRoundedRectangle(0, 0, getWidth(), getHeight(), 5.f, 2);
g.drawFittedText(name, 0, 0, getWidth(), getHeight(), Justification::centred, 1, 1.f);

}

else
{
float number = name.substring(6, 5).getDoubleValue();
if(isMouseDown)
g.setColour(genericColour.darker(.2f));
else
g.setColour(genericColour.darker(.6f));

g.fillRoundedRectangle(getLocalBounds().toFloat(), 5.f);
g.setColour(Colours::white);
g.drawRoundedRectangle(getLocalBounds().toFloat(), 5.f, 2);
g.drawFittedText(name, getLocalBounds(), Justification::centred, 1, 1.f);
}
}

String name;
int currentTab;
bool active;
bool isMouseDown;
String type;
Colour genericColour;

};

//============================================================
// class for displaying popup text
//============================================================
class HelpComp : public Component
{
public:
HelpComp():firstTime(true)
{
this->setInterceptsMouseClicks(false, false);
setSize(10, 50);
}

~HelpComp() {};

void setText(String _info, String _syntax)
{
syntax=_syntax;
info=_info;
repaint();
}

void paint(Graphics& g)
{
g.fillAll(Colour::fromRGB(10, 10, 10));
g.setColour(Colours::yellow);
g.drawRect(0, 0, getWidth()-1, getHeight()-1, 1);
g.setFont(14);
g.setColour(Colours::cornflowerblue);
g.drawFittedText(syntax, 10, 5, getWidth(), getHeight(), Justification::topLeft, 100, 1);
int width = Font(14).getStringWidth(syntax);
g.setColour(Colours::white);
g.drawFittedText(info, width+30, 4, getWidth(), getHeight(), Justification::topLeft, 100, 1);
}

void resized()
{
setSize(getWidth(), getHeight());
}

bool firstTime;
private:

String syntax, info;

};

//============================================================
// class for displaying popup text
//============================================================
class SearchReplaceComp : public Component,
public TextEditor::Listener,
public ChangeBroadcaster
{
public:
ScopedPointer<FlatButton> searchButton, replaceAllButton, replaceOnceButton;

SearchReplaceComp()
{
addAndMakeVisible(searchEditor = new TextEditor("SearchEditor"));
searchEditor->addListener(this);
addAndMakeVisible(replaceEditor = new TextEditor("ReplaceWithEditor"));
replaceEditor->addListener(this);
addAndMakeVisible(searchButton = new FlatButton("Search", 0, ""));
searchButton->setName("SearchButton");
addAndMakeVisible(replaceOnceButton = new FlatButton("Replace Once", 0, ""));
replaceOnceButton->setName("ReplaceOnceButton");
replaceOnceButton->genericColour = Colours::cornflowerblue;
addAndMakeVisible(replaceAllButton = new FlatButton("Replace All", 0, ""));
replaceAllButton->genericColour = Colours::cornflowerblue;
replaceAllButton->setName("ReplaceAllButton");
addAndMakeVisible(findLabel = new Label("FindLabel"));
addAndMakeVisible(replaceLabel = new Label("ReplaceLabel"));

replaceLabel->setText("Replace with:", dontSendNotification);
replaceLabel->setColour(Label::textColourId, Colours::whitesmoke);
findLabel->setText("Find:", dontSendNotification);
findLabel->setColour(Label::textColourId, Colours::whitesmoke);

replaceEditor->setColour(TextEditor::backgroundColourId, Colours::whitesmoke);
replaceEditor->setColour(TextEditor::textColourId, Colours::black);
replaceEditor->setColour(CaretComponent::caretColourId, Colours::black);

searchEditor->setColour(TextEditor::backgroundColourId, Colours::whitesmoke);
searchEditor->setColour(TextEditor::textColourId, Colours::black);
searchEditor->setColour(CaretComponent::caretColourId, Colours::black);
}

~SearchReplaceComp() {};

void paint(Graphics& g)
{
g.fillAll(CabbageUtils::getDarkerBackgroundSkin());
}

void resized()
{
findLabel->setBounds(0, 4, 30, 20);
searchEditor->setBounds(35, 4, 150, 20);
searchButton->setBounds(190, 4, 100, 20);
replaceLabel->setBounds(295, 4, 50, 20);
replaceEditor->setBounds(350, 4, 150, 20);
replaceOnceButton->setBounds(505, 4, 100, 20);
replaceAllButton->setBounds(610 , 4, 100, 20);
}

String getSearchText()
{
return searchEditor->getText();
}

void setSearchText(String text)
{
if(! text.containsAnyOf ("\r\n"))
searchEditor->setText(text);
else
searchEditor->setText("");
}

String getReplaceText()
{
return replaceEditor->getText();
}

void textEditorReturnKeyPressed (TextEditor &editor)
{
currentEditorName = editor.getName();
sendChangeMessage();
}

String getCurrentTextEditor()
{
return currentEditorName;
}

private:

String currentEditorName;
ScopedPointer<TextEditor> searchEditor, replaceEditor;
ScopedPointer<Label> findLabel, replaceLabel;
String syntax, info;

};
#endif

+ 868
- 653
ports/cabbage/source/Editor/CodeWindow.cpp
File diff suppressed because it is too large
View File


+ 206
- 502
ports/cabbage/source/Editor/CodeWindow.h View File

@@ -22,523 +22,227 @@
#include "CodeEditor.h"
#include "KeyboardShortcuts.h"
#include "SplitComponent.h"
#include "../Plugin/CabbagePluginProcessor.h"
//class LiveCsound;
class PythonEditor;
class PopupDisplay;
//==============================================================================
//Main window. This window holds a 2 textEditors. One for the code, and the other for
//displaying Csound output messages
//==============================================================================
class CodeWindow : public DocumentWindow,
public ApplicationCommandTarget,
public MenuBarModel,
public ActionListener,
public ActionBroadcaster,
public CodeDocument::Listener,
public Timer
//========== csound output console class =================
class CsoundOutputComponent : public Component
{
ScopedPointer<TextEditor> textEditor;
public:
CodeWindow(String name);
~CodeWindow();
CodeDocument csoundDoc;
//==============================================================================
StringArray getMenuBarNames()
{
const char* const names[] = { "File", "Edit", "Help", 0 };
return StringArray (names);
}
//==============================================================================
void getAllCommands (Array <CommandID>& commands)
{
const CommandID ids[] = {
CommandIDs::fileNew,
CommandIDs::fileOpen,
CommandIDs::fileSave,
CommandIDs::fileSaveAs,
CommandIDs::fileQuit,
CommandIDs::fileKeyboardShorts,
CommandIDs::editUndo,
CommandIDs::editCopy,
CommandIDs::editCut,
CommandIDs::editPaste,
CommandIDs::editRedo,
CommandIDs::editToggleComments,
CommandIDs::editZoomIn,
CommandIDs::editZoomOut,
CommandIDs::whiteBackground,
CommandIDs::blackBackground,
CommandIDs::startSession,
CommandIDs::insertFromRepo,
CommandIDs::AudioSettings,
CommandIDs::addFromRepo,
CommandIDs::insertRecentEvent,
CommandIDs::openPythonEditor,
CommandIDs::commOrchUpdateInstrument,
CommandIDs::commOrchUpdateMultiLine,
CommandIDs::commOrchUpdateSingleLine,
CommandIDs::commScoUpdateMultiLine,
CommandIDs::commScoUpdateSingleLine,
CommandIDs::commOrcUpdateChannel,
CommandIDs::viewCsoundHelp,
CommandIDs::viewCabbageHelp
};
commands.addArray (ids, sizeof (ids) / sizeof (ids [0]));
}
//==============================================================================
void menuItemSelected (int menuItemID, int topLevelMenuIndex){
if (menuItemID >= 100 && menuItemID < 200)
{
RecentlyOpenedFilesList recentFiles;
recentFiles.restoreFromString (appProperties->getUserSettings()
->getValue ("recentlyOpenedFiles"));
csdFile = recentFiles.getFile (menuItemID - 100);
textEditor->getDocument().replaceAllContent(csdFile.loadFileAsString());
setName(csdFile.getFullPathName());
}
}
//==============================================================================
void setFontSize(String zoom)
{
if(zoom==String("in"))
textEditor->setFont(Font(String("Courier New"), ++fontSize, 1));
else
textEditor->setFont(Font(String("Courier New"), --fontSize, 1));
}
//================= command methods ====================
ApplicationCommandTarget* getNextCommandTarget(){
return findFirstTargetParentComponent();
}
void getCommandInfo (const CommandID commandID, ApplicationCommandInfo& result);
PopupMenu getMenuForIndex (int topLevelMenuIndex, const String& menuName);
bool perform (const InvocationInfo& info);
void toggleManuals(String manual);
void setEditorColourScheme(String theme);
void actionListenerCallback(const String &message);
void timerCallback();
void toggleTextWindows();
Rectangle<int> getCaretScreenPosition(){
Rectangle<int> rect(textEditor->getCaretPoisition());
rect.setLeft(rect.getX()+this->getTopLevelComponent()->getX()+100);
rect.setTop(rect.getY()+this->getTopLevelComponent()->getY()+45);
return rect;
}
void closeButtonPressed(){
//JUCEApplication::getInstance()->systemRequestedQuit();
this->setVisible(false);
}
void codeDocumentTextDeleted(int,int){}
void codeDocumentTextInserted(const juce::String &,int){}
void codeDocumentChanged (const CodeDocument::Position &affectedTextStart, const CodeDocument::Position &affectedTextEnd);
void insertFromRepo();
void setText(String file){
csoundDoc.replaceAllContent(file);
}
String getText(){
return csoundDoc.getAllContent();
}
void setColourScheme(String theme){
if(theme=="white"){
textEditor->setColourScheme(csoundToker.getDefaultColourScheme());
textEditor->setColour(CodeEditorComponent::backgroundColourId, Colours::white);
textEditor->setColour(CaretComponent::caretColourId, Colours::black);
textEditor->setColour(CodeEditorComponent::highlightColourId, Colours::cornflowerblue);
appProperties->getUserSettings()->setValue("EditorColourScheme", 0);
}
else if(theme=="dark"){
textEditor->setColourScheme(csoundToker.getDarkColourScheme());
textEditor->setColour(CaretComponent::caretColourId, Colours::white);
textEditor->setColour(CodeEditorComponent::backgroundColourId, Colour::fromRGB(20, 20, 20));
textEditor->setColour(CodeEditorComponent::highlightColourId, Colours::green.withAlpha(.6f));
appProperties->getUserSettings()->setValue("EditorColourScheme", 1);
}
}
void newFile(String type);
bool unSaved;
StringArray recentEvents;
//ScopedPointer<CabbageLookAndFeel> lookAndFeel;
String csoundOutputText;
bool firstTime;
String debugMessage;
bool showOutput;
CommandManager commandManager;
File csdFile;
int fontSize;
String ASCIICabbage;
StringArray opcodeStrings;
ScopedPointer<PopupDisplay> popupDisplay;
CsoundCodeEditor* textEditor;
CsoundTokeniser csoundToker;
Font font;
ScopedPointer<WebBrowserComponent> htmlHelp;
bool showingHelp;
};
CsoundOutputComponent(String title): Component()
{
textEditor = new TextEditor();
textEditor->setColour(Label::outlineColourId, Colours::white);
textEditor->setColour(TextEditor::backgroundColourId, CabbageUtils::getDarkerBackgroundSkin());
textEditor->setColour(TextEditor::textColourId, Colours::cornflowerblue);
textEditor->setMultiLine(true);
textEditor->setFont(Font("Arial", 14, 0));
addAndMakeVisible(textEditor, true);
setText("hewe;roiuew asdfhsa ldkjfhsd lfauskdhf lsadiufh dslifuhsadlifu hdsaflisaud hflidsau hflidsa uf");
};
~CsoundOutputComponent() {};
void setText(String text)
{
textEditor->setColour(TextEditor::textColourId, Colours::cornflowerblue);
textEditor->setText(text);
textEditor->setCaretPosition(textEditor->getText().length());
}
String getText()
{
return textEditor->getText();
}
void resized()
{
textEditor->setBounds(20, 21, getWidth()-25, getHeight()-30);
}
void paint(Graphics& g)
{
g.fillAll(CabbageUtils::getDarkerBackgroundSkin());
g.setColour(Colours::white);
g.drawRoundedRectangle(getLocalBounds().toFloat(), 2, 2);
g.drawFittedText("Csound output", getLocalBounds().withHeight(18), Justification::centred, 1, 1.f);
}
//============================================================
// window for Python editor
//============================================================
class PythonEditor: public DocumentWindow,
public ActionListener,
public ActionBroadcaster
{
public:
PythonEditor(String name):DocumentWindow (name, Colours::black,
DocumentWindow::closeButton)
{
textEditor = new CsoundCodeEditor("python", csoundDocu, &csoundToker);
textEditor->setColour(TextEditor::textColourId, Colours::white);
textEditor->setFont(Font(String("Courier New"), 15, 1));
textEditor->addActionListener(this);
textEditor->setSize(600, 400);
if(!appProperties->getUserSettings()->getValue("EditorColourScheme", var(0)).getIntValue())
setEditorColourScheme("white");
else if(appProperties->getUserSettings()->getValue("EditorColourScheme", var(0)).getIntValue())
setEditorColourScheme("dark");
centreWithSize(600, 400);
setContentNonOwned(textEditor, true);
setResizable(true, false);
}
~PythonEditor()
{
delete textEditor;
}
void codeDocumentChanged (const CodeDocument::Position &affectedTextStart, const CodeDocument::Position &affectedTextEnd)
{
}
void actionListenerCallback(const String &message)
{
if(message=="make invisible"){
//this->setVisible(false);
sendActionMessage("sendPythonEvent");
//if(textEditor->getm)
}
}
void closeButtonPressed(){
setVisible(false);
}
void setEditorColourScheme(String theme){
if(theme=="white"){
textEditor->setColourScheme(csoundToker.getDefaultColourScheme());
textEditor->setColour(CodeEditorComponent::backgroundColourId, Colours::white);
textEditor->setColour(CaretComponent::caretColourId, Colours::black);
textEditor->setColour(CodeEditorComponent::highlightColourId, Colours::cornflowerblue);
appProperties->getUserSettings()->setValue("EditorColourScheme", 0);
}
else if(theme=="dark"){
textEditor->setColourScheme(csoundToker.getDarkColourScheme());
textEditor->setColour(CaretComponent::caretColourId, Colours::white);
textEditor->setColour(CodeEditorComponent::backgroundColourId, Colour::fromRGB(20, 20, 20));
textEditor->setColour(CodeEditorComponent::highlightColourId, Colours::green.withAlpha(.6f));
appProperties->getUserSettings()->setValue("EditorColourScheme", 1);
}
}
void codeDocumentTextDeleted(int,int){}
void codeDocumentTextInserted(const juce::String &,int){}
CsoundCodeEditor* textEditor;
CodeDocument csoundDocu;
PythonTokeniser csoundToker;
};
//============================================================
// audio settings class (not currently used...)
//============================================================
class AudioSettings: public Component,
public ActionListener,
public ActionBroadcaster
//========== csound debugger output console class =================
class CsoundDebuggerComponent : public Component
{
ScopedPointer<TextEditor> textEditor;
public:
AudioSettings(StringArray deviceStrings)
{
addAndMakeVisible (label = new Label ("new label",
"Sampling Rate"));
label->setFont (Font (15.00f, Font::bold));
label->setJustificationType (Justification::centredLeft);
label->setEditable (false, false, false);
label->setColour (TextEditor::textColourId, Colours::lime);
label->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
addAndMakeVisible (samplingRate = new ComboBox ("new combo box"));
samplingRate->addItem("44100", 1);
samplingRate->addItem("48000", 2);
samplingRate->setSelectedId(1, dontSendNotification );
samplingRate->setEditableText (false);
samplingRate->setJustificationType (Justification::centredLeft);
samplingRate->setTextWhenNothingSelected (String::empty);
samplingRate->setTextWhenNoChoicesAvailable ("(no choices)");
//samplingRate->addListener (this);
addAndMakeVisible (label2 = new Label ("new label",
"Ksmps"));
label2->setFont (Font (20.00f, Font::bold));
label2->setJustificationType (Justification::centredLeft);
label2->setEditable (false, false, false);
label2->setColour (TextEditor::textColourId, Colours::lime);
label2->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
addAndMakeVisible (ksmps = new ComboBox ("new combo box"));
ksmps->addItem("32", 1);
ksmps->addItem("64", 2);
ksmps->addItem("128", 3);
ksmps->addItem("512", 4);
ksmps->addItem("1024", 5);
ksmps->addItem("2048", 6);
ksmps->addItem("4096", 7);
ksmps->setSelectedId(2, dontSendNotification );
ksmps->setEditableText (false);
ksmps->setJustificationType (Justification::centredLeft);
ksmps->setTextWhenNothingSelected (String::empty);
ksmps->setTextWhenNoChoicesAvailable ("(no choices)");
// ksmps->addListener (this);
addAndMakeVisible (label3 = new Label ("new label",
"Audio Device"));
label3->setFont (Font (15.00f, Font::bold));
label3->setJustificationType (Justification::centredLeft);
label3->setEditable (false, false, false);
label3->setColour (TextEditor::textColourId, Colours::lime);
label3->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
addAndMakeVisible (audioDevice = new ComboBox ("new combo box"));
audioDevice->setEditableText (false);
for(int i=0;i<deviceStrings.size();i++)
audioDevice->addItem(deviceStrings[i], i+1);
audioDevice->setSelectedId(deviceStrings.size(), dontSendNotification );
audioDevice->setJustificationType (Justification::centredLeft);
audioDevice->setTextWhenNothingSelected (String::empty);
audioDevice->setTextWhenNoChoicesAvailable ("(no choices)");
//audioDevice->addListener (this);
addAndMakeVisible (label4 = new Label ("new label",
"MIDI Device"));
label4->setFont (Font (15.00f, Font::bold));
label4->setJustificationType (Justification::centredLeft);
label4->setEditable (false, false, false);
label4->setColour (TextEditor::textColourId, Colours::lime);
label4->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
addAndMakeVisible (midiDevice = new ComboBox ("new combo box"));
midiDevice->setEditableText (false);
midiDevice->setJustificationType (Justification::centredLeft);
midiDevice->setTextWhenNothingSelected (String::empty);
midiDevice->setTextWhenNoChoicesAvailable ("(no choices)");
//midiDevice->addListener (this);
setSize(300, 200);
}
void actionListenerCallback(const String &message)
{
if(message=="make invisible"){
//this->setVisible(false);
sendActionMessage("sendPythonEvent");
}
}
void resized(){
label->setBounds (28, 16, 96, 24);
samplingRate->setBounds (130, 16, 118, 24);
label2->setBounds (58, 52, 80, 24);
ksmps->setBounds (130, 52, 117, 24);
label3->setBounds (41, 87, 80, 24);
audioDevice->setBounds (130, 88, 117, 24);
label4->setBounds (42, 122, 80, 24);
midiDevice->setBounds (130, 121, 118, 24);
}
void paint(Graphics& g){
g.fillAll(Colours::black);
}
~AudioSettings(){
label = nullptr;
samplingRate = nullptr;
label2 = nullptr;
ksmps = nullptr;
label3 = nullptr;
audioDevice = nullptr;
label4 = nullptr;
midiDevice = nullptr;
}
private:
ScopedPointer<Label> label;
ScopedPointer<ComboBox> samplingRate;
ScopedPointer<Label> label2;
ScopedPointer<ComboBox> ksmps;
ScopedPointer<Label> label3;
ScopedPointer<ComboBox> audioDevice;
ScopedPointer<Label> label4;
ScopedPointer<ComboBox> midiDevice;
};
CsoundDebuggerComponent(String title): Component()
{
textEditor = new TextEditor();
textEditor->setColour(Label::outlineColourId, Colours::white);
textEditor->setColour(TextEditor::backgroundColourId, CabbageUtils::getDarkerBackgroundSkin());
textEditor->setColour(TextEditor::textColourId, Colours::white);
textEditor->setMultiLine(true);
#if defined(WIN32)
textEditor->setFont(Font(String("Consolas"), 13, 1));
#elif defined(MACOSX)
textEditor->setFont(Font(String("Courier New"), 13, 1));
#else
textEditor->setFont(Font(String("Droid Sans Mono"), 13, 1));
#endif
addAndMakeVisible(textEditor, true);
};
~CsoundDebuggerComponent() {};
void setText(String text)
{
StringArray textArray;
textArray.addLines(text);
textArray.removeEmptyStrings(true);
for(int i=2; i<textArray.size(); i++)
{
StringArray tempArray;
String formattedLine="";
tempArray.addTokens(textArray[i], " ");
tempArray.removeDuplicates(true);
tempArray.removeEmptyStrings();
for(int j=0; j<tempArray.size(); j++)
{
formattedLine+=tempArray[j].removeCharacters(" ").paddedRight(' ', 20);
textArray.set(i, formattedLine);
}
}
textEditor->setColour(TextEditor::textColourId, Colours::lime);
textEditor->setText(textArray.joinIntoString("\n"));
}
String getText()
{
return textEditor->getText();
}
void resized()
{
textEditor->setBounds(20, 21, getWidth()-25, getHeight()-30);
}
void paint(Graphics& g)
{
g.fillAll(CabbageUtils::getDarkerBackgroundSkin());
g.setColour(Colours::white);
g.drawRoundedRectangle(getLocalBounds().toFloat(), 2, 2);
g.drawFittedText("Debugger output", getLocalBounds().withHeight(18), Justification::centred, 1, 1.f);
}
//============================================================
// class for displaying popup text
//============================================================
class PopupDisplay : public DialogWindow,
public Timer,
public ActionBroadcaster
};
//==============================================================================
//Main window. This window holds a 2 textEditors. One for the code, and the other for
//displaying Csound output messages
//==============================================================================
class CodeWindow : public DocumentWindow,
public ApplicationCommandTarget,
public MenuBarModel,
public ActionListener,
public ActionBroadcaster,
public CodeDocument::Listener,
public Timer
{
class Box : public Component
{
public:
Box():firstTime(true)
{
this->setInterceptsMouseClicks(false, false);
setSize(10, 50);
}
~Box(){};
void setText(String _info, String _syntax){
syntax=_syntax;
info=_info;
repaint();
}
void paint(Graphics& g)
{
#ifdef LINUX
g.fillAll(Colour::fromRGB(40,40,40));
g.setColour(Colours::yellow);
g.drawRect(0, 0, getWidth()-1, getHeight()-1, 1);
g.setFont(Font(String("Arial"), 16, 0));
g.setColour(Colours::whitesmoke);
g.drawFittedText(syntax, 10, 10, getWidth(), getHeight(), Justification::topLeft, 100, 1);
g.setFont(Font(String("Arial"), 15, 0));
g.setColour(Colours::cornflowerblue);
g.drawFittedText(info, 10, 25, getWidth(), getHeight(), Justification::topLeft, 100, 1);
#else
g.fillAll(Colour::fromRGB(20, 20, 20));
g.setColour(Colours::whitesmoke);
g.drawRect(0, 0, getWidth()-1, getHeight()-1, 1);
g.setFont(Font(String("Arial"), 16, 0));
g.setColour(Colours::yellow);
g.drawFittedText(syntax, 10, 10, getWidth(), getHeight(), Justification::topLeft, 100, 1);
g.setFont(Font(String("Arial"), 15, 0));
g.setColour(Colours::lime);
g.drawFittedText(info, 10, 25, getWidth(), getHeight(), Justification::topLeft, 100, 1);
#endif
}
void resized(){
setSize(getWidth(), getHeight());
}
bool firstTime;
private:
String syntax, info;
};
public:
PopupDisplay(String name): DialogWindow(name, Colours::black, true, true),
time(0), seconds(0)
{
box = new Box();
this->setContentNonOwned(box, true);
#ifndef LINUX
this->setAlpha(.9f);
#endif
}
~PopupDisplay(){}
void resized(){
setSize(getWidth(), 50);
// box->repaint();
}
void setText(String opcodeName, String opcodeDescrptor){
box->setText(opcodeName, opcodeDescrptor);
}
int getDesktopWindowStyleFlags() const{
int styleFlags = ComponentPeer::windowAppearsOnTaskbar;
//if (useDropShadow) styleFlags |= ComponentPeer::windowHasDropShadow;
//if (useNativeTitleBar) styleFlags |= ComponentPeer::windowHasTitleBar;
return 0;
}
void timerCallback(){
if(time<seconds){
time++;
stopTimer();
setVisible(true);
sendActionMessage("");
}
}
void killSplash(){
box->firstTime=false;
box->repaint();
}
bool triggerToAppear(int _seconds)
{
time=0;
seconds = _seconds;
startTimer(1000);
}
void closeButtonPressed(){
setVisible(false);
}
ScopedPointer<Box> box;
int time;
int seconds;
CodeWindow(String name);
~CodeWindow();
CodeDocument csoundDoc;
StringArray getMenuBarNames();
void getAllCommands (Array <CommandID>& commands);
void menuItemSelected (int menuItemID, int topLevelMenuIndex);
void setFontSize(String zoom);
//================= command methods ====================
ApplicationCommandTarget* getNextCommandTarget()
{
return findFirstTargetParentComponent();
}
void getCommandInfo (const CommandID commandID, ApplicationCommandInfo& result);
PopupMenu getMenuForIndex (int topLevelMenuIndex, const String& menuName);
bool perform (const InvocationInfo& info);
void toggleManuals(String manual);
void setEditorColourScheme(String theme);
void actionListenerCallback(const String &message);
void timerCallback();
void toggleTextWindows();
juce::Rectangle<int> getCaretScreenPosition()
{
juce::Rectangle<int> rect(textEditor->editor[textEditor->currentEditor]->getCaretPoisition());
rect.setLeft(rect.getX()+this->getTopLevelComponent()->getX()+100);
rect.setTop(rect.getY()+this->getTopLevelComponent()->getY()+45);
return rect;
}
void closeButtonPressed()
{
//JUCEApplication::getInstance()->systemRequestedQuit();
this->setVisible(false);
}
void codeDocumentTextDeleted(int,int) {}
void showCabbageHelp();
void codeDocumentTextInserted(const juce::String &,int) {}
void codeDocumentChanged (const CodeDocument::Position &affectedTextStart, const CodeDocument::Position &affectedTextEnd);
void insertFromRepo();
void setText(String text, String file)
{
textEditor->setAllText(text);
textEditor->openFiles.getReference(0) = file;
}
String getText()
{
return textEditor->getAllText();
}
void setColourScheme(String theme);
void newFile(String type);
bool unSaved;
StringArray recentEvents;
String csoundOutputText;
bool firstTime;
String debugMessage;
bool showOutput;
CommandManager commandManager;
File csdFile;
int fontSize;
String ASCIICabbage;
ScopedPointer<SplitComponent> splitWindow;
ScopedPointer<SplitComponent> splitBottomWindow;
ScopedPointer<CsoundOutputComponent> csoundOutputComponent;
ScopedPointer<CsoundDebuggerComponent> csoundDebuggerComponent;
StringArray opcodeStrings;
CsoundCodeEditor* textEditor;
CsoundTokeniser csoundToker;
Font font;
bool isColumnModeEnabled;
bool isInstrTabEnabled;
bool isCsoundOutputEnabled;
};
#endif // __MAINCOMPONENT_H_615ECE56__

+ 1
- 1
ports/cabbage/source/Editor/CommandManager.cpp View File

@@ -2,7 +2,7 @@
//==============================================================================
CommandManager::CommandManager () :
ApplicationCommandManager ()
ApplicationCommandManager ()
{
}


+ 47
- 44
ports/cabbage/source/Editor/CommandManager.h View File

@@ -24,55 +24,58 @@
//==============================================================================
namespace CommandIDs
{
static const int fileNew = 1000;
static const int fileOpen = 1001;
static const int fileSave = 1002;
static const int fileSaveAs = 1003;
static const int fileSaveAll = 1004;
static const int fileExportSynth = 1005;
static const int fileExportEffect = 1006;
static const int fileUpdateGUI = 1007;
static const int fileQuit = 1008;
static const int fileKeyboardShorts = 1009;
static const int editUndo = 2011;
static const int editRedo = 2012;
static const int editCut = 2013;
static const int editCopy = 2014;
static const int editPaste = 2015;
static const int editZoomIn = 2016;
static const int editZoomOut = 2017;
static const int whiteBackground = 2018;
static const int blackBackground = 2019;
static const int editToggleComments = 2020;
static const int insertFromRepo = 2021;
static const int addFromRepo = 2022;
static const int insertRecentEvent = 2023;
static const int openPythonEditor = 2024;
static const int viewCsoundHelp = 4025;
static const int viewCabbageHelp = 4026;
static const int viewSource = 4027;
static const int AudioSettings = 4028;
static const int startSession = 3023;
static const int commOrchUpdateInstrument = 3024;
static const int commOrchUpdateSingleLine = 3025;
static const int commOrchUpdateMultiLine = 3026;
static const int commScoUpdateMultiLine = 3027;
static const int commScoUpdateSingleLine = 3028;
static const int commOrcUpdateChannel = 3029;
static const int fileNew = 1000;
static const int fileOpen = 1001;
static const int fileSave = 1002;
static const int fileSaveAs = 1003;
static const int fileSaveAll = 1004;
static const int fileExportSynth = 1005;
static const int fileExportEffect = 1006;
static const int fileUpdateGUI = 1007;
static const int fileQuit = 1008;
static const int fileCloseAux = 2081;
static const int fileKeyboardShorts = 1009;
static const int editUndo = 2011;
static const int editRedo = 2012;
static const int editCut = 2013;
static const int editCopy = 2014;
static const int editPaste = 2015;
static const int editSearchReplace = 2080;
static const int editColumnEdit = 2082;
static const int editZoomIn = 2016;
static const int editZoomOut = 2017;
static const int whiteBackground = 2018;
static const int blackBackground = 2019;
static const int editToggleComments = 2020;
static const int insertFromRepo = 2021;
static const int addFromRepo = 2022;
static const int insertRecentEvent = 2023;
static const int openPythonEditor = 2024;
static const int setBreakpoint = 3000;
static const int removeBreakpoint = 3001;
static const int continueDebug = 3002;
static const int nextDebug = 3003;
static const int viewCsoundHelp = 4025;
static const int viewCabbageHelp = 4026;
static const int viewCsoundOutput = 4032;
static const int viewSource = 4027;
static const int viewOpcodeHelp = 4028;
static const int viewLinesNumbers = 4029;
static const int viewInstrumentsTabs = 4030;
};
//==============================================================================
namespace CommandCategories
{
static const char* const file = "File";
static const char* const edit = "Edit";
static const char* const command = "Command";
static const char* const help = "View";
static const char* const file = "File";
static const char* const edit = "Edit";
static const char* const view = "View";
static const char* const debug = "Debug";
static const char* const help = "Help";
}
//==============================================================================
@@ -81,10 +84,10 @@ class CommandManager : public ApplicationCommandManager
{
public:
CommandManager ();
CommandManager ();
~CommandManager ();
juce_DeclareSingleton (CommandManager, true)
juce_DeclareSingleton (CommandManager, true)
};


+ 205
- 168
ports/cabbage/source/Editor/CsoundTokeniser.h
File diff suppressed because it is too large
View File


+ 41
- 39
ports/cabbage/source/Editor/KeyboardShortcuts.h View File

@@ -11,45 +11,47 @@
class ShortcutsPanel : public PropertyPanel
{
public:
ShortcutsPanel() : PropertyPanel()
{
setSize(200, 300);
Array <PropertyComponent*> props;
keyboardShortcutsXml = appProperties->getUserSettings()->getXmlValue("KeyboardShortcutXmlData");

for(int i=0;i<keyboardShortcutsXml->getNumAttributes();i++)
{
textFields.add(Value(keyboardShortcutsXml->getAttributeValue(i)));
attributeNames.add(keyboardShortcutsXml->getAttributeName(i));
props.add(new TextPropertyComponent(textFields[i],
keyboardShortcutsXml->getAttributeName(i),
100, false));
props[i]->setPreferredHeight(20);
props[i]->setColour(TextPropertyComponent::backgroundColourId, Colours::red);
}
setSize(200, jmin(300, props.size()*props[0]->getPreferredHeight()));
addProperties(props);
}
void paint(Graphics &g){
g.fillAll(Colours::lightgrey);
}
~ShortcutsPanel(){
for(int i=0;i<keyboardShortcutsXml->getNumAttributes();i++)
keyboardShortcutsXml->setAttribute(attributeNames[i], textFields[i].toString());
appProperties->getUserSettings()->setValue("KeyboardShortcutXmlData", keyboardShortcutsXml);
Logger::writeToLog("update all variables before closing");
keyboardShortcutsXml = nullptr;
}
Array<Value> textFields;
ScopedPointer<XmlElement> keyboardShortcutsXml;
StringArray attributeNames;
ShortcutsPanel() : PropertyPanel()
{
setSize(200, 300);
Array <PropertyComponent*> props;
keyboardShortcutsXml = appProperties->getUserSettings()->getXmlValue("KeyboardShortcutXmlData");

for(int i=0; i<keyboardShortcutsXml->getNumAttributes(); i++)
{
textFields.add(Value(keyboardShortcutsXml->getAttributeValue(i)));
attributeNames.add(keyboardShortcutsXml->getAttributeName(i));

props.add(new TextPropertyComponent(textFields[i],
keyboardShortcutsXml->getAttributeName(i),
100, false));

props[i]->setPreferredHeight(20);
props[i]->setColour(TextPropertyComponent::backgroundColourId, Colours::red);
}

setSize(200, jmin(300, props.size()*props[0]->getPreferredHeight()));
addProperties(props);
}

void paint(Graphics &g)
{
g.fillAll(Colours::lightgrey);
}

~ShortcutsPanel()
{
for(int i=0; i<keyboardShortcutsXml->getNumAttributes(); i++)
keyboardShortcutsXml->setAttribute(attributeNames[i], textFields[i].toString());
appProperties->getUserSettings()->setValue("KeyboardShortcutXmlData", keyboardShortcutsXml);
Logger::writeToLog("update all variables before closing");
keyboardShortcutsXml = nullptr;
}

Array<Value> textFields;
ScopedPointer<XmlElement> keyboardShortcutsXml;
StringArray attributeNames;

};



+ 201
- 198
ports/cabbage/source/Editor/PythonTokeniser.h View File

@@ -25,10 +25,10 @@
class PythonTokeniser : public CodeTokeniser
{
public:
PythonTokeniser(){}
~PythonTokeniser(){}
//==============================================================================
PythonTokeniser() {}
~PythonTokeniser() {}
//==============================================================================
enum TokenType
{
tokenType_error = 0,
@@ -42,111 +42,111 @@ public:
tokenType_bracket,
tokenType_punctuation,
tokenType_preprocessor,
tokenType_csdTag
tokenType_csdTag
};

CodeEditorComponent::ColourScheme getDefaultColourScheme()
{
struct Type
{
const char* name;
uint32 colour;
};
const Type types[] =
{
{ "Error", Colours::black.getARGB() },
{ "Comment", Colours::green.getARGB() },
{ "Keyword", Colours::blue.getARGB() },
{ "Identifier", Colours::black.getARGB() },
{ "Integer", Colours::orange.getARGB() },
{ "Float", Colours::black.getARGB() },
{ "String", Colours::red.getARGB() },
{ "Operator", Colours::pink.getARGB() },
{ "Bracket", Colours::darkgreen.getARGB() },
{ "Punctuation", Colours::black.getARGB() },
{ "Preprocessor Text", Colours::green.getARGB() },
{ "Csd Tag", Colours::brown.getARGB() }
};
CodeEditorComponent::ColourScheme cs;
for (int i = 0; i < sizeof (types) / sizeof (types[0]); ++i) // (NB: numElementsInArray doesn't work here in GCC4.2)
cs.set (types[i].name, Colour (types[i].colour));
return cs;
}
CodeEditorComponent::ColourScheme getDarkColourScheme()
{
struct Type
{
const char* name;
uint32 colour;
};
const Type types[] =
{
{ "Error", Colours::white.getARGB() },
{ "Comment", Colours::green.getARGB() },
{ "Keyword", Colours::cornflowerblue.getARGB() },
{ "Identifier", Colours::white.getARGB() },
{ "Integer", Colours::orange.getARGB() },
{ "Float", Colours::lime.getARGB() },
{ "String", Colours::red.getARGB() },
{ "Operator", Colours::pink.getARGB() },
{ "Bracket", Colours::darkgreen.getARGB() },
{ "Punctuation", Colours::white.getARGB() },
{ "Preprocessor Text", Colours::green.getARGB() },
{ "Csd Tag", Colours::brown.getARGB() }
};
CodeEditorComponent::ColourScheme cs;
for (int i = 0; i < sizeof (types) / sizeof (types[0]); ++i) // (NB: numElementsInArray doesn't work here in GCC4.2)
cs.set (types[i].name, Colour (types[i].colour));
return cs;
}
CodeEditorComponent::ColourScheme getDefaultColourScheme()
{
struct Type
{
const char* name;
uint32 colour;
};
const Type types[] =
{
{ "Error", Colours::black.getARGB() },
{ "Comment", Colours::green.getARGB() },
{ "Keyword", Colours::blue.getARGB() },
{ "Identifier", Colours::black.getARGB() },
{ "Integer", Colours::orange.getARGB() },
{ "Float", Colours::black.getARGB() },
{ "String", Colours::red.getARGB() },
{ "Operator", Colours::pink.getARGB() },
{ "Bracket", Colours::darkgreen.getARGB() },
{ "Punctuation", Colours::black.getARGB() },
{ "Preprocessor Text", Colours::green.getARGB() },
{ "Csd Tag", Colours::brown.getARGB() }
};
CodeEditorComponent::ColourScheme cs;
for (int i = 0; i < sizeof (types) / sizeof (types[0]); ++i) // (NB: numElementsInArray doesn't work here in GCC4.2)
cs.set (types[i].name, Colour (types[i].colour));
return cs;
}
CodeEditorComponent::ColourScheme getDarkColourScheme()
{
struct Type
{
const char* name;
uint32 colour;
};
const Type types[] =
{
{ "Error", Colours::white.getARGB() },
{ "Comment", Colours::green.getARGB() },
{ "Keyword", Colours::cornflowerblue.getARGB() },
{ "Identifier", Colours::white.getARGB() },
{ "Integer", Colours::orange.getARGB() },
{ "Float", Colours::lime.getARGB() },
{ "String", Colours::red.getARGB() },
{ "Operator", Colours::pink.getARGB() },
{ "Bracket", Colours::darkgreen.getARGB() },
{ "Punctuation", Colours::white.getARGB() },
{ "Preprocessor Text", Colours::green.getARGB() },
{ "Csd Tag", Colours::brown.getARGB() }
};
CodeEditorComponent::ColourScheme cs;
for (int i = 0; i < sizeof (types) / sizeof (types[0]); ++i) // (NB: numElementsInArray doesn't work here in GCC4.2)
cs.set (types[i].name, Colour (types[i].colour));
return cs;
}


private:
//==============================================================================
StringArray getTokenTypes()
{
StringArray s;
s.add ("Error");
s.add ("Comment");
s.add ("C++ keyword");
s.add ("Identifier");
s.add ("Integer literal");
s.add ("Float literal");
s.add ("String literal");
s.add ("Operator");
s.add ("Bracket");
s.add ("Punctuation");
s.add ("Preprocessor line");
s.add ("CSD Tag");
return s;
}

//==============================================================================
void skipQuotedString (CodeDocument::Iterator& source)
{
const juce_wchar quote = source.nextChar();
for (;;)
//==============================================================================
StringArray getTokenTypes()
{
const juce_wchar c = source.nextChar();
if (c == quote || c == 0)
break;
StringArray s;
s.add ("Error");
s.add ("Comment");
s.add ("C++ keyword");
s.add ("Identifier");
s.add ("Integer literal");
s.add ("Float literal");
s.add ("String literal");
s.add ("Operator");
s.add ("Bracket");
s.add ("Punctuation");
s.add ("Preprocessor line");
s.add ("CSD Tag");
return s;
}

if (c == '\\')
source.skip();
}
}
//==============================================================================
void skipQuotedString (CodeDocument::Iterator& source)
{
const juce_wchar quote = source.nextChar();
for (;;)
{
const juce_wchar c = source.nextChar();
if (c == quote || c == 0)
break;

if (c == '\\')
source.skip();
}
}


//==============================================================================
//==============================================================================
void skipCSDTag (CodeDocument::Iterator& source) noexcept
{
for (;;)
@@ -157,68 +157,69 @@ private:
}
}

//==============================================================================
bool isIdentifierStart (const char c)
{
return CharacterFunctions::isLetter (c)
|| c == '_' || c == '@';
}
//==============================================================================
bool isIdentifierBody (const char c)
{
return CharacterFunctions::isLetter (c)
|| CharacterFunctions::isDigit (c)
|| c == '_' || c == '@';
}
//==============================================================================
//==============================================================================
bool isIdentifierStart (const char c)
{
return CharacterFunctions::isLetter (c)
|| c == '_' || c == '@';
}
//==============================================================================
bool isIdentifierBody (const char c)
{
return CharacterFunctions::isLetter (c)
|| CharacterFunctions::isDigit (c)
|| c == '_' || c == '@';
}
//==============================================================================
bool isReservedKeyword (String::CharPointerType token, const int tokenLength) noexcept
{
//populate char array with Csound keywords
//this list of keywords is not completely up to date!
static const char* const keywords[] =
{
"and",
"as",
"assert",
"break",
"class",
"continue",
"def",
"del",
"elif",
"else",
"except",
"exec",
"finally",
"for",
"from",
"global",
"if",
"import",
"in",
"is",
"lambda",
"not",
"or",
"pass",
"print",
"raise",
"return",
"try",
"while",
"with",
"yield"};
//populate char array with Csound keywords
//this list of keywords is not completely up to date!
static const char* const keywords[] =
{
"and",
"as",
"assert",
"break",
"class",
"continue",
"def",
"del",
"elif",
"else",
"except",
"exec",
"finally",
"for",
"from",
"global",
"if",
"import",
"in",
"is",
"lambda",
"not",
"or",
"pass",
"print",
"raise",
"return",
"try",
"while",
"with",
"yield"
};


const char* const* k;

if (tokenLength < 2 || tokenLength > 16)
return false;
if (tokenLength < 2 || tokenLength > 16)
return false;

else
k = keywords;
else
k = keywords;


int i = 0;
@@ -232,8 +233,8 @@ private:
return false;
}

//==============================================================================
int parseIdentifier (CodeDocument::Iterator& source) noexcept
//==============================================================================
int parseIdentifier (CodeDocument::Iterator& source) noexcept
{
int tokenLength = 0;
String::CharPointerType::CharType possibleIdentifier [100];
@@ -260,50 +261,52 @@ private:
return CsoundTokeniser::tokenType_identifier;
}

//==============================================================================
int readNextToken (CodeDocument::Iterator& source)
{
int result = tokenType_error;
source.skipWhitespace();
char firstChar = source.peekNextChar();

switch (firstChar)
//==============================================================================
int readNextToken (CodeDocument::Iterator& source)
{
case 0:
source.skip();
break;

case ';':
source.skipToEndOfLine();
result = tokenType_comment;
break;

case '"':
// case T('\''):
skipQuotedString (source);
result = tokenType_stringLiteral;
break;

case '<':
source.skip();
if((source.peekNextChar() == 'C') ||
(source.peekNextChar() == '/')){
skipCSDTag (source);
result = tokenType_csdTag;
}
break;

default:
if (isIdentifierStart (firstChar)){
result = parseIdentifier (source);
}
else
int result = tokenType_error;
source.skipWhitespace();
char firstChar = source.peekNextChar();

switch (firstChar)
{
case 0:
source.skip();
break;
break;

case ';':
source.skipToEndOfLine();
result = tokenType_comment;
break;

case '"':
// case T('\''):
skipQuotedString (source);
result = tokenType_stringLiteral;
break;

case '<':
source.skip();
if((source.peekNextChar() == 'C') ||
(source.peekNextChar() == '/'))
{
skipCSDTag (source);
result = tokenType_csdTag;
}
break;

default:
if (isIdentifierStart (firstChar))
{
result = parseIdentifier (source);
}
else
source.skip();
break;
}
//jassert (result != tokenType_unknown);
return result;
}
//jassert (result != tokenType_unknown);
return result;
}
};

#endif

+ 408
- 0
ports/cabbage/source/Editor/SplitComponent.cpp View File

@@ -0,0 +1,408 @@
/*
==============================================================================
Split component for Juce
File: SplitComponent.cpp
Created: 15 Mar 2014
--------------------------------------------------------------------------------
Copyright 2014 Jim Hewes
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================
*/
#include <cassert>
#include "SplitComponent.h"
SplitComponent::SplitComponent(bool isVertical)
: m_pTopLeftComponent(NULL)
, m_pBottomRightComponent(NULL)
, m_isVertical(isVertical)
, m_splitBarGravity(0.0)
, m_fitToParent(true)
{
CommonConstruction();
}
SplitComponent::SplitComponent(Component& topLeftComponent, Component& bottomRightComponent, bool isVertical)
: m_pTopLeftComponent(&topLeftComponent)
, m_pBottomRightComponent(&bottomRightComponent)
, m_isVertical(isVertical)
, m_splitBarGravity(0.0)
, m_fitToParent(false)
{
CommonConstruction();
}
void SplitComponent::CommonConstruction()
{
// Set the bounds of this split component based on the parent's size (if there is a parent).
parentSizeChanged();
m_pSplitBar = new SplitBar(*this, m_isVertical);
// set default position and width of the SplitBar
if (m_isVertical)
{
m_pSplitBar->setBounds(getWidth() / 2, 0, 8, getHeight());
m_lastSplitbarMovePosition = m_pSplitBar->getX();
m_lastSplitbarMoveExtent = getWidth();
}
else
{
m_pSplitBar->setBounds(0, getHeight() / 2, getWidth(), 8);
m_lastSplitbarMovePosition = m_pSplitBar->getY();
m_lastSplitbarMoveExtent = getHeight();
}
if (m_pTopLeftComponent)
{
addAndMakeVisible(m_pTopLeftComponent, 0);
}
if (m_pBottomRightComponent)
{
addAndMakeVisible(m_pBottomRightComponent, 1);
}
addAndMakeVisible(m_pSplitBar, -1); // make sure the split bar is in front of other components.
}
SplitComponent::~SplitComponent()
{
removeAllChildren();
}
void SplitComponent::SetTopLeftComponent(Component &component)
{
if (m_pTopLeftComponent)
{
removeChildComponent(m_pTopLeftComponent);
}
m_pTopLeftComponent = &component;
addAndMakeVisible(m_pTopLeftComponent, 0);
Layout();
}
void SplitComponent::SetBottomRightComponent(Component &component)
{
if (m_pBottomRightComponent)
{
removeChildComponent(m_pBottomRightComponent);
}
m_pBottomRightComponent = &component;
addAndMakeVisible(m_pBottomRightComponent, 1);
Layout();
}
void SplitComponent::Layout()
{
Rectangle<int> topLeftComponentRect;
Rectangle<int> bottomRightComponentRect;
topLeftComponentRect.setTop(0);
topLeftComponentRect.setLeft(0);
if (m_isVertical)
{
int splitBarPosX = m_pSplitBar->getX();
int splitBarWidth = m_pSplitBar->getWidth();
topLeftComponentRect.setWidth(splitBarPosX);
topLeftComponentRect.setHeight(getHeight());
bottomRightComponentRect.setPosition(splitBarPosX + splitBarWidth, 0);
bottomRightComponentRect.setWidth(getWidth() - (splitBarPosX + splitBarWidth));
bottomRightComponentRect.setHeight(getHeight());
}
else
{
int splitBarPosY = m_pSplitBar->getY();
int splitBarHeight = m_pSplitBar->getHeight();
topLeftComponentRect.setWidth(getWidth());
topLeftComponentRect.setHeight(splitBarPosY);
bottomRightComponentRect.setPosition(0, splitBarPosY + splitBarHeight);
bottomRightComponentRect.setWidth(getWidth());
bottomRightComponentRect.setHeight(getHeight() - (splitBarPosY + splitBarHeight));
}
if (m_pTopLeftComponent)
{
m_pTopLeftComponent->setBounds(topLeftComponentRect);
}
if (m_pBottomRightComponent)
{
m_pBottomRightComponent->setBounds(bottomRightComponentRect);
}
}
void SplitComponent::SetSplitBarPosition(int newPosition)
{
if (m_isVertical)
{
newPosition = jmax(0, jmin(newPosition, getWidth() - m_pSplitBar->getWidth())); // limit
m_pSplitBar->setBounds(newPosition, 0, m_pSplitBar->getWidth(), m_pSplitBar->getHeight());
m_lastSplitbarMoveExtent = getWidth();
}
else
{
newPosition = jmax(0, jmin(newPosition, getHeight() - m_pSplitBar->getHeight())); // limit
m_pSplitBar->setBounds(0, newPosition, m_pSplitBar->getWidth(), m_pSplitBar->getHeight());
m_lastSplitbarMoveExtent = getHeight();
}
m_lastSplitbarMovePosition = newPosition;
Layout();
}
int SplitComponent::GetSplitBarPosition() const
{
return m_isVertical ? m_pSplitBar->getX() : m_pSplitBar->getY();
}
void SplitComponent::SetSplitBarThickness(int newThickness)
{
// The position of the split bar may now be invalid as a result of the new thickness, so adjust.
int splitBarPosition;
if (m_isVertical)
{
newThickness = jmax(0, jmin(newThickness, getWidth() - 2));
splitBarPosition = jmin(m_pSplitBar->getX(), getWidth() - newThickness); // limit split bar position
m_pSplitBar->setBounds(splitBarPosition, 0, newThickness, m_pSplitBar->getHeight());
}
else
{
newThickness = jmax(0, jmin(newThickness, getHeight() - 2));
splitBarPosition = jmin(m_pSplitBar->getY(), getHeight() - newThickness);
m_pSplitBar->setBounds(0, splitBarPosition, m_pSplitBar->getWidth(), newThickness);
}
SetSplitBarPosition(splitBarPosition);
}
int SplitComponent::GetSplitBarThickness() const
{
return m_isVertical ? m_pSplitBar->getWidth() : m_pSplitBar->getHeight();
}
void SplitComponent::SetSplitBarGravity(double gravity)
{
assert((gravity >= 0.0) && (gravity <= 1.0));
// limit
m_splitBarGravity = (gravity < 0.0) ? 0.0 : (gravity > 1.0) ? 1.0 : gravity;
}
double SplitComponent::GetSplitBarGravity() const
{
return m_splitBarGravity;;
}
void SplitComponent::SetVerticalSplit(bool isVertical)
{
if (m_isVertical != isVertical)
{
// Change the orientation of the split bar.
// The split bar position might now be invalid (outside the SplitComponent bounds). So move it to be valid.
int splitbarThickness;
int splitBarPosition;
if (m_isVertical) // change from vertical to horizontal
{
splitbarThickness = m_pSplitBar->getWidth();
splitBarPosition = m_pSplitBar->getX();
// limit split bar position
splitBarPosition = jmin(splitBarPosition, getHeight() - splitbarThickness);
m_pSplitBar->setBounds(0, splitBarPosition, getWidth(), splitbarThickness);
}
else // change from horizontal to vertical
{
splitbarThickness = m_pSplitBar->getHeight();
splitBarPosition = m_pSplitBar->getY();
// limit split bar position
splitBarPosition = jmin(splitBarPosition, getWidth() - splitbarThickness);
m_pSplitBar->setBounds(splitBarPosition, 0, splitbarThickness, getHeight());
}
m_pSplitBar->SetVertical(isVertical);
m_isVertical = isVertical;
SetSplitBarPosition(splitBarPosition);
}
}
bool SplitComponent::IsVerticalSplit() const
{
return m_isVertical;
}
void SplitComponent::SetFitToParent(bool fitToParent)
{
if (m_fitToParent != fitToParent)
{
m_fitToParent = fitToParent;
parentSizeChanged();
}
}
bool SplitComponent::GetFitToParent() const
{
return m_fitToParent;
}
void SplitComponent::resized()
{
if (m_isVertical)
{
// Account for gravity
int widthDiff = getWidth() - m_lastSplitbarMoveExtent; // Get the difference in SplitComponent width since the split bar was moved manually.
widthDiff = int(widthDiff * m_splitBarGravity); // Get a percentage of that difference based on the gravity setting.
int newXPosition = widthDiff + m_lastSplitbarMovePosition; // Add the difference to getthe new desired right position. (which may get limited below)
// Keep the split bar inside the visible area
int maxSplitPosition = getWidth() - m_pSplitBar->getWidth();
newXPosition = juce::jmax(0, juce::jmin(maxSplitPosition, newXPosition));
// Essentially, adjust the height of the split bar to be the height of the SplitComponent.
m_pSplitBar->setBounds(newXPosition, 0, m_pSplitBar->getWidth(), getHeight());
}
else
{
// Account for gravity
int heightDiff = getHeight() - m_lastSplitbarMoveExtent; // Get the difference in SplitComponent width since the split bar was moved manually.
heightDiff = int(heightDiff * m_splitBarGravity); // Get a percentage of that difference based on the gravity setting.
int newYPosition = heightDiff + m_lastSplitbarMovePosition; // Add the difference to getthe new desired right position. (which may get limited below)
// Keep the split bar inside the visible area
newYPosition = juce::jlimit(0, getHeight() - m_pSplitBar->getHeight(), newYPosition);
// Essentially, adjust the width of the split bar to be the width of the SplitComponent.
m_pSplitBar->setBounds(0, newYPosition, getWidth(), m_pSplitBar->getHeight());
}
Layout();
}
/**
Resize the SplitComponent to fills the area of it's parent if fit-to-parent is set.
*/
void SplitComponent::parentSizeChanged()
{
Component* pParentComponent = getParentComponent();
if (pParentComponent && m_fitToParent)
{
// Occupy the entire space of the parent component.
// Use Rectangle::setPosition(0,0) and NOT Rectangle::setLeft(0) Rectangle::setTop(0).
// The later two would change the width and height of the rectangle so that the right and
// bottom edges stay in the same place. setPosition does not have that side effect.
Rectangle<int> bounds = pParentComponent->getBounds();
bounds.setPosition(0, 0);
setBounds(bounds); // This will cause SplitComponent::resized() to be called.
}
}
void SplitComponent::parentHierarchyChanged()
{
// If the parent changed, we no longer know if the split bar position is within the parent's bounds.
// So treat it as if the parent size changed. This also takes care of the case where a SplitComponent is added
// to a parent for the first time and the split position was not initialized.
parentSizeChanged();
}
//////////////////////////////////////////////////////////////////////////////////////////////////
//
// Splitbar
//
//
SplitComponent::SplitBar::SplitBar(SplitComponent& splitComponent, bool isVertical)
: m_isVertical(isVertical)
, m_splitComponent(splitComponent)
{
setRepaintsOnMouseActivity(true);
setMouseCursor(isVertical ? MouseCursor::LeftRightResizeCursor : MouseCursor::UpDownResizeCursor);
}
void SplitComponent::SplitBar::paint(Graphics& g)
{
getLookAndFeel().drawStretchableLayoutResizerBar(g,
getWidth(), getHeight(),
m_isVertical,
isMouseOver(),
isMouseButtonDown());
}
void SplitComponent::SplitBar::mouseDown(const MouseEvent&)
{
const Point<int> pos = getPosition();
m_mouseDownPos = m_isVertical ? pos.getX() : pos.getY();
}
void SplitComponent::SplitBar::mouseDrag(const MouseEvent& e)
{
int desiredPos = m_mouseDownPos + (m_isVertical ? e.getDistanceFromDragStartX() : e.getDistanceFromDragStartY());
// Adjust position to keep the split bar inside the SplitComponent bounds.
desiredPos = jmax(desiredPos, 0);
if (m_isVertical)
{
desiredPos = jmin(desiredPos, m_splitComponent.getWidth() - getWidth());
}
else
{
desiredPos = jmin(desiredPos, m_splitComponent.getHeight() - getHeight());
}
if (desiredPos != m_mouseDownPos)
{
m_splitComponent.SetSplitBarPosition(desiredPos);
}
}
void SplitComponent::SplitBar::SetVertical(bool isVertical)
{
if (m_isVertical != isVertical)
{
m_isVertical = isVertical;
setMouseCursor(m_isVertical ? MouseCursor::LeftRightResizeCursor : MouseCursor::UpDownResizeCursor);
}
}
bool SplitComponent::SplitBar::IsVertical()
{
return m_isVertical;
}

+ 273
- 0
ports/cabbage/source/Editor/SplitComponent.h View File

@@ -0,0 +1,273 @@
/*
==============================================================================
Split component for Juce
File: SplitComponent.h
Created: 15 Mar 2014
--------------------------------------------------------------------------------
Copyright 2014 Jim Hewes
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================
*/
#ifndef SPLITCOMPONENT_H_INCLUDED
#define SPLITCOMPONENT_H_INCLUDED
#include "../JuceHeader.h"
/**
SplitComponent is a simple "splitter window" in which two child components are divided by a split bar that can be moved.\n
\n
SplitComponent is useful when you want to divide an area into two halves and let the user move a middle split bar
to resize the halves. You can split the area either vertically or horizontally. You can also set a "gravity" amount for
the middle split bar so that when you resize the window the split bar will move proportionally to grow or shrink the
child components.\n
\n
By default, a SplitComponent fills the entire area of it's parent. To limit its size within the parent, call
FitToParent(false) and then set the bounds as needed.
\n
SplitComponents can be nested so that you can create more complex divisions, but since a SplitComponent fills the entire
area of it's parent, it should be put inside another component first.
\n
To use the SplitComponent, you supply two child components to be the left and right sides (or top and bottom for a
horzontal split). Here's an example:
@code{.cpp}
MyLeftComponent myLeftComponent;
MyRightComponent myRightComponent;
SplitComponent* pSplitComponent = new SplitComponent(myLeftComponent, myRightComponent);
pSplitComponent->SetSplitBarPosition(getWidth() / 2); // Set the split bar to halfway so the area is divided equally.
// The split bar thickness is 8 pixels by default, but you can change it.
addAndMakeVisible(pSplitComponent); // Add the SplitComponent to this component is, (Maybe the MainComponent)
@endcode
If it's more convenient, you can construct an empty SplitComponent first, and then add the left and right child components later.\n
\n
Note that when the SplitComponent is resized or its split bar is moved, it resizes the child components.
So if you have a child component that wants to resize itself according to its parent's size (for example, it
fills the area of its parent) you need to first enclose it in another component. This can be as simple as
just a Component object. For example, say that MyLeftComponent above wants to fill the area of its parent,
you could implement it like this:
@code{.cpp}
MyLeftComponent myLeftComponent;
MyRightComponent myRightComponent;
Component leftPanel;
leftPanel.addAndMakeVisible(myLeftComponent);
SplitComponent* pSplitComponent = new SplitComponent(leftPanel, myRightComponent);
...etc.
@endcode
This would be the case when nesting a SplitComponent that is set to fit to the area of it's parent.\n
\n
The split bar conforms to whatever look and feel you've set since it calls drawStretchableLayoutResizerBar() to paint itself.
*/
class SplitComponent : public Component
{
public:
SplitComponent(bool isVertical = true);
SplitComponent(Component& topLeftComponent, Component& bottomRightComponent, bool isVertical = true);
virtual ~SplitComponent();
/**
Sets (or replaces) the top component if the SplitComponent is horizontal, or the left component if the SplitComponent is vertical.
The SplitComponent does not own the top/left component. It is not deleted when the SplitComponent is deleted.
The caller must delete it.
*/
void SetTopLeftComponent(Component &component);
/**
Sets (or replaces) the bottom component if the SplitComponent is horizontal, or the right component if the SplitComponent is vertical.
The SplitComponent does not own the bottom/right component. It is not deleted when the SplitComponent is deleted.
The caller must delete it.
*/
void SetBottomRightComponent(Component &component);
/**
Sets the splitbar position vertically in terms of pixels if this is a horizontal SplitComponent.\n
Sets the splitbar position horizontally in terms of pixels if this is a vertical SplitComponent.\n
The position to which the split bar is actually set will be adjusted so it is inside the SplitComponent.
@param[in] newPositionInPixels The new top/left position of the split bar. For a vertical split, the
position will be limited to the width of the SplitComponent minus the
thickness of the split bar. For a horizontal split, the position will
be limited to the width of the SplitComponent minus the thickness of
the split bar.
*/
void SetSplitBarPosition(int newPositionInPixels);
/**
Gets the splitbar vertical position in terms of pixels if this is a horizontal SplitComponent.
Sets the splitbar horizontal position in terms of pixels if this is a vertical SplitComponent.
@returns The current split bar position.
*/
int GetSplitBarPosition() const;
/**
Enables or disables the SplitComponent to always entirely fill it parent's client area.
@param[in] fitToParent If true, the SplitComponent will always entirely fill it parent's client area. (The default)
If false, the not fill it parent's client area, in which case you must set the bounds
of the SplitContainer to be what you want.
@see GetFitToParent
*/
void SetFitToParent(bool fitToParent);
/**
Retrieves the current state of the fit-to-parent setting.
@retval true If the SplitComponent is set to entirely fill it parent's client area.
@retval false If the SplitComponent is notset to entirely fill it parent's client area.
@see SetFitToParent
*/
bool GetFitToParent() const;
/**
Sets the splitbar width in terms of pixels if this is a vertical SplitComponent.\n
Sets the splitbar height in terms of pixels if this is a horizontal SplitComponent.\n
The splitbar thickness can be set to 0 pixels in which case it's not visible and the
user cannot move it. But its position can still be set programatically.
@param[in] newThicknessInPixels The new width/height of the split bar.
@see GetSplitBarThickness
*/
void SetSplitBarThickness(int newThicknessInPixels);
/**
Gets the splitbar width in terms of pixels if this is a vertical SplitComponent.\n
Gets the splitbar height in terms of pixels if this is a horizontal SplitComponent.\n
@returns The current split bar thickness.
@see SetSplitBarThickness
*/
int GetSplitBarThickness() const;
/**
Sets the amount by which each component grows or shrinks when the windows is resized.
- 0.0 means only the bottom/right component is resized. (The default)
- 0.5 means each component is resized equally.
- 1.0 means only the top/left component is resized.
@param[in] gravity The gravity of the split bar. A value between 0.0 and 1.0.
@see GetSplitBarGravity
*/
void SetSplitBarGravity(double gravity);
/**
Gets the amount by which each component grows or shrinks when he windows is resized.
@returns The current gravity of the split bar. A value between 0.0 and 1.0.
@see SetSplitBarGravity
*/
double GetSplitBarGravity() const;
/**
Sets the split direction of the SplitComponent.
@param[in] isVertical If true, the split direction will be set (changed) to be vertical.
If false, the split direction will be set (changed) to be horizontal.
@see IstVerticalSplit
*/
void SetVerticalSplit(bool isVertical);
/**
Gets the split direction of the SplitComponent.
@retval true The split direction is currently vertical.
@retval false The split direction is currently horizontal.
@see SetVerticalSplit
*/
bool IsVerticalSplit() const;
/** Called when this component's immediate parent has been resized.
@see resized, parentHierarchyChanged
*/
void parentSizeChanged() override;
void resized() override;
/**
This is defined for when the SplitContainer is added to a parent. It will resize itself to that parent.
*/
void parentHierarchyChanged() override;
private:
class SplitBar : public Component
{
public:
SplitBar(SplitComponent& splitComponent, bool isVertical);
void SetVertical(bool isVertical);
bool IsVertical();
void paint(Graphics&) override;
void mouseDown(const MouseEvent&) override;
void mouseDrag(const MouseEvent&) override;
private:
bool m_isVertical;
SplitComponent& m_splitComponent;
int m_mouseDownPos;
};
void CommonConstruction();
/**
Lays out the two components on either side of the split bar by setting their bounds according to where the split bar is.
Layout assumes that the split bar bounds and position have already been set.
*/
void Layout();
bool m_isVertical;
bool m_fitToParent;
ScopedPointer<SplitBar> m_pSplitBar;
Component* m_pTopLeftComponent; ///< A pointer to the top component if the splitter is horizontal, or the left component if the splitter is vertical.
Component* m_pBottomRightComponent; ///< A pointer to the bottom component if the splitter is horizontal, or the right component if the splitter is vertical.
double m_splitBarGravity;
// The following two values are used with gravity. The purpose of keeping these two is to avoid having the
// splitbar walk left or right due to accumulated roundoff error when the SplitComponent is resized many times.
int m_lastSplitbarMovePosition; ///< The position of the split bar the last time it was moved manually or programmatically. (Not as a result of a window resize)
int m_lastSplitbarMoveExtent; ///< The width/height of the SplitComponent the last time the split bar was moved manually or programmatically. (Not as a result of a window resize)
};
#endif // SPLITCOMPONENT_H_INCLUDED

+ 1915
- 1792
ports/cabbage/source/Editor/opcodes.txt
File diff suppressed because it is too large
View File


+ 2
- 0
ports/cabbage/source/JuceHeader.h View File

@@ -16,6 +16,8 @@
#include "AppConfig.h"
#include "JucePluginCharacteristics.h"
#define UseNativeDialogue 0
#include "modules/juce_audio_basics/juce_audio_basics.h"
#include "modules/juce_audio_devices/juce_audio_devices.h"
#include "modules/juce_audio_formats/juce_audio_formats.h"


+ 2
- 2
ports/cabbage/source/JucePluginCharacteristics.h View File

@@ -59,10 +59,10 @@
#endif
#define JucePlugin_SilenceInProducesSilenceOut 1
#define JucePlugin_TailLengthSeconds 0
#define JucePlugin_TailLengthSeconds 0
#define JucePlugin_EditorRequiresKeyboardFocus 1
#define JucePlugin_VersionCode 0x10000
#define JucePlugin_VersionString "0.0.0"
#define JucePlugin_VersionString "1.0.0"
#define JucePlugin_VSTUniqueID JucePlugin_PluginCode
#define JucePlugin_VSTCategory kPlugCategEffect
#define JucePlugin_AUSubType JucePlugin_PluginCode


+ 82
- 82
ports/cabbage/source/Plugin/CabbageGenericAudioProcessorEditor.h View File

@@ -4,7 +4,7 @@
Cabbage is free software; you can redistribute it
and/or modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
version 2.1 of the License, or (at your option) any later version.

Cabbage is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -29,35 +29,35 @@
#include "../CabbageLookAndFeel.h"

class ProcessorParameterPropertyComp : public PropertyComponent,
public AudioProcessorListener,
public Timer
public AudioProcessorListener,
public Timer
{
//==============================================================================
//==============================================================================
class ParamSlider : public Slider,
public ActionBroadcaster
// public ActionListener
public ActionBroadcaster
// public ActionListener
{
public:
ParamSlider (AudioProcessor& owner_, const int index_)
: owner (owner_),
index (index_)
{
//basicLookAndFeel = new CabbageLookAndFeelBasic();
setLookAndFeel(basicLookAndFeel);
this->setColour(Slider::textBoxBackgroundColourId, CabbageUtils::getBackgroundSkin());
//basicLookAndFeel = new CabbageLookAndFeelBasic();
setLookAndFeel(basicLookAndFeel);
this->setColour(Slider::textBoxBackgroundColourId, CabbageUtils::getBackgroundSkin());

setRange (0.0, 1.0, 0.0);
setSliderStyle (Slider::LinearHorizontal);
setTextBoxStyle (Slider::TextBoxLeft, false, 80, 15);
setSliderStyle (Slider::LinearHorizontal);
setTextBoxStyle (Slider::TextBoxLeft, false, 80, 15);
setTextBoxIsEditable (false);
setScrollWheelEnabled (false);
}

void valueChanged()
{
//this return the name of the plugin
//this calls ProcessorParameterPropertyComp::actionListenerCallbck
this->sendActionMessage("");
//this return the name of the plugin
//this calls ProcessorParameterPropertyComp::actionListenerCallbck
this->sendActionMessage("");
const float newVal = (float) getValue();

if (owner.getParameter (index) != newVal)
@@ -75,15 +75,15 @@ class ProcessorParameterPropertyComp : public PropertyComponent,
//==============================================================================
AudioProcessor& owner;
const int index;
ScopedPointer<CabbageLookAndFeelBasic> basicLookAndFeel;
ScopedPointer<CabbageLookAndFeelBasic> basicLookAndFeel;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ParamSlider);
};


public:
ParamSlider slider;
Colour highlightColour;
bool moddedText;
ParamSlider slider;
Colour highlightColour;
bool moddedText;

ProcessorParameterPropertyComp (const String& name, AudioProcessor& owner_, const int index_)
: PropertyComponent (name),
@@ -92,12 +92,12 @@ public:
paramHasChanged (false),
slider (owner_, index_)
{
moddedText = false;
setPreferredHeight(20);
startTimer (100);
moddedText = false;
setPreferredHeight(20);
startTimer (100);
addAndMakeVisible (&slider);
owner_.addListener (this);
highlightColour = CabbageUtils::getDarkerBackgroundSkin();
highlightColour = CabbageUtils::getDarkerBackgroundSkin();
}

~ProcessorParameterPropertyComp()
@@ -107,7 +107,7 @@ public:

void refresh()
{
paramHasChanged = false;
paramHasChanged = false;
slider.setValue (owner.getParameter (index), sendNotification);
}

@@ -133,30 +133,30 @@ public:
}
}

void paint(Graphics &g)
{
g.fillAll(CabbageUtils::getComponentSkin().darker(.4f)); //background
String text = getName();
if(moddedText)
g.setColour(Colours::yellow);
else
g.setColour(Colours::whitesmoke);
Font font (CabbageUtils::getTitleFont());
//font.setFallbackFontName (String("Verdana")); //in case the user doesn't have the first font installed
g.setFont (font);
g.drawFittedText(text, 5, 5,
font.getStringWidth(text), font.getHeight()-2, Justification::centredTop, 1);
// g.drawFittedText(text, 5, 5,
// font.getStringWidth(text), font.getHeight()-2, Justification::centredTop, 1);
}
void paint(Graphics &g)
{
g.fillAll(CabbageUtils::getComponentSkin().darker(.4f)); //background
String text = getName();
if(moddedText)
g.setColour(Colours::yellow);
else
g.setColour(Colours::whitesmoke);
Font font (CabbageUtils::getTitleFont());
//font.setFallbackFontName (String("Verdana")); //in case the user doesn't have the first font installed
g.setFont (font);
g.drawFittedText(text, 5, 5,
font.getStringWidth(text), font.getHeight()-2, Justification::centredTop, 1);
// g.drawFittedText(text, 5, 5,
// font.getStringWidth(text), font.getHeight()-2, Justification::centredTop, 1);
}


private:

ScopedPointer<CabbageLookAndFeelBasic> basicLookAndFeel;
ScopedPointer<CabbageLookAndFeelBasic> basicLookAndFeel;
AudioProcessor& owner;
const int index;
bool volatile paramHasChanged;
@@ -170,58 +170,58 @@ class CabbageGenericAudioProcessorEditor : public AudioProcessorEditor
public:
//==============================================================================

CabbageGenericAudioProcessorEditor(AudioProcessor* const owner_)
: AudioProcessorEditor (owner_)
{
jassert (owner_ != nullptr);
setOpaque (true);
basicLookAndFeel = new CabbageLookAndFeelBasic();
this->setLookAndFeel(basicLookAndFeel);
addAndMakeVisible (&panel);
CabbageGenericAudioProcessorEditor(AudioProcessor* const owner_)
: AudioProcessorEditor (owner_)
{
jassert (owner_ != nullptr);
setOpaque (true);
basicLookAndFeel = new CabbageLookAndFeelBasic();
this->setLookAndFeel(basicLookAndFeel);
addAndMakeVisible (&panel);

Array <PropertyComponent*> params;
Array <PropertyComponent*> params;

const int numParams = owner_->getNumParameters();
Logger::writeToLog("NumParameters:" +String(numParams));
int totalHeight = 0;
const int numParams = owner_->getNumParameters();
Logger::writeToLog("NumParameters:" +String(numParams));
int totalHeight = 0;

for (int i = 0; i < numParams; ++i)
{
String name (owner_->getParameterName (i));
if (name.trim().isEmpty())
name = "Unnamed";
for (int i = 0; i < numParams; ++i)
{
String name (owner_->getParameterName (i));
if (name.trim().isEmpty())
name = "Unnamed";

ProcessorParameterPropertyComp* const pc = new ProcessorParameterPropertyComp (name, *owner_, i);
params.add (pc);
totalHeight += pc->getPreferredHeight();
}
ProcessorParameterPropertyComp* const pc = new ProcessorParameterPropertyComp (name, *owner_, i);

panel.addProperties (params);
params.add (pc);
totalHeight += pc->getPreferredHeight();
}

setSize (400, jlimit (25, 400, totalHeight));
}
panel.addProperties (params);

~CabbageGenericAudioProcessorEditor()
{
}
setSize (400, jlimit (25, 400, totalHeight));
}

~CabbageGenericAudioProcessorEditor()
{
}


void paint (Graphics& g)
{
//background
g.setColour(Colour::fromRGB(20, 20, 20));
g.fillAll();
}
void paint (Graphics& g)
{
//background
g.setColour(Colour::fromRGB(20, 20, 20));
g.fillAll();
}


void resized()
{
panel.setBounds (getLocalBounds());
}
void resized()
{
panel.setBounds (getLocalBounds());
}


ScopedPointer<CabbageLookAndFeelBasic> basicLookAndFeel;
ScopedPointer<CabbageLookAndFeelBasic> basicLookAndFeel;
private:
//==============================================================================
PropertyPanel panel;


+ 2965
- 2918
ports/cabbage/source/Plugin/CabbagePluginEditor.cpp
File diff suppressed because it is too large
View File


+ 197
- 148
ports/cabbage/source/Plugin/CabbagePluginEditor.h View File

@@ -4,7 +4,7 @@
Cabbage is free software; you can redistribute it
and/or modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
version 2.1 of the License, or (at your option) any later version.
Cabbage is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -23,7 +23,6 @@
#include "../CabbageCustomWidgets.h"
#include "../JuceHeader.h"
#include "CabbagePluginProcessor.h"
//#include "../CabbageLookAndFeel.h"
#include "../CabbagePropertiesDialog.h"
#include "../CabbageUtils.h"
@@ -34,49 +33,88 @@ class CabbageMainPanel;
class ComponentLayoutEditor;
class CabbageCornerResizer;
//==============================================================================
// window used to display popup plants
//==============================================================================
class CabbagePlantWindow : public DocumentWindow
{
public:
CabbagePlantWindow(const String& title, const Colour& backgroundColour)
: DocumentWindow (title, backgroundColour, DocumentWindow::closeButton){};
~CabbagePlantWindow(){
};
CabbagePlantWindow(const String& title, const Colour& backgroundColour)
: DocumentWindow (title, backgroundColour, DocumentWindow::closeButton)
{
setName(title);
};
~CabbagePlantWindow()
{
};
void closeButtonPressed(){
// void mouseMove(const MouseEvent& event)
// {
// Logger::writeToLog("planty");
// //Logger::writeToLog(String(this->getContentComponent()->getMouseXYRelative().getX()));
// }
//
//
void closeButtonPressed()
{
setMinimised(true);
setVisible(false);
setAlwaysOnTop(false);
};
setAlwaysOnTop(false);
};
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CabbagePlantWindow);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CabbagePlantWindow);
};
//==============================================================================
// component that sits inside of main viewport class
//==============================================================================
class CabbageViewportComponent : public Component
{
public:
CabbageViewportComponent() : Component("CabbageViewportComponent")
{
this->setInterceptsMouseClicks(false, true);
}
~CabbageViewportComponent() {}
void paint(Graphics &g)
{
Viewport* const viewport = findParentComponentOfClass<Viewport>(); //Get the parent viewport
if(viewport != nullptr) //Check for nullness
{
juce::Rectangle<int> viewRect(viewport->getViewPositionX(), viewport->getViewPositionY(), viewport->getViewWidth(), viewport->getViewHeight()); //Get the current displayed area in the viewport
}
}
};
//==============================================================================
// pointData class for holding info about each segment of a line
class PointData
//==============================================================================
class PointData
{
public:
Point <int> point;
int curveType;
PointData(Point<int> point, int curveType):point(point),curveType(curveType)
{}
~PointData(){}
Point <int> point;
int curveType;
PointData(Point<int> point, int curveType):point(point),curveType(curveType)
{}
~PointData() {}
};
//==============================================================================
// main GUI editor window
//==============================================================================
class CabbagePluginAudioProcessorEditor : public AudioProcessorEditor,
public CabbageUtils,
public SliderListener,
public ComboBoxListener,
public ButtonListener,
public KeyListener,
public ChangeBroadcaster,
public ChangeListener,
public ActionListener,
public Timer
public CabbageUtils,
public SliderListener,
public ComboBoxListener,
public ButtonListener,
public KeyListener,
public ChangeBroadcaster,
public ChangeListener,
public ActionListener
{
public:
CabbagePluginAudioProcessorEditor (CabbagePluginAudioProcessor* ownerFilter);
@@ -84,124 +122,134 @@ public:
void paint (Graphics& g);
void resized();
void setEditMode(bool on);
void InsertGUIControls(CabbageGUIClass cAttr);
void ksmpsYieldCallback();
void updateSize();
ScopedPointer<CabbagePropertiesDialog> propsWindow;
//main GUI controls vectors..
OwnedArray<Component> comps;
OwnedArray<Component> layoutComps;
void updateLayoutEditorFrames();
ScopedPointer<CabbageTable> cabTable;
ScopedPointer<CabbageCornerResizer> resizer;
void setEditMode(bool on);
void InsertGUIControls(CabbageGUIClass cAttr);
void ksmpsYieldCallback();
void updateSize();
ScopedPointer<CabbagePropertiesDialog> propsWindow;
//main GUI controls vectors..
OwnedArray<Component> comps;
OwnedArray<Component> layoutComps;
void updateLayoutEditorFrames();
ScopedPointer<CabbageTable> cabTable;
ScopedPointer<CabbageCornerResizer> resizer;
Point<int> getMousePos();
Array<int> popupMenus;
void updateGUIControls();
OwnedArray<CabbagePlantWindow> subPatches;
//CabbagePluginAudioProcessor* filter;
CabbagePluginAudioProcessor* getFilter() const
{
return static_cast <CabbagePluginAudioProcessor*> (getAudioProcessor());
}
int currentPopupIndex;
private:
void createfTableData(Table* table);
bool keyPressed(const juce::KeyPress &,Component *);
void updateSizesAndPositionsOfComponents(int newLine = 0);
void deleteComponents();
void duplicateComponents();
void populateLineNumberArray(StringArray csdArray);
void addToRepository(String entryName);
void convertIntoPlant();
void breakUpPlant();
void InsertGroupBox(CabbageGUIClass &cAttr);
void comboBoxChanged (ComboBox* combo);
void InsertComboBox(CabbageGUIClass &cAttr);
void InsertSoundfiler(CabbageGUIClass &cAttr);
void InsertDirectoryList(CabbageGUIClass &cAttr);
void SetupWindow(CabbageGUIClass &cAttr);
void InsertSlider(CabbageGUIClass &cAttr);
void sliderValueChanged (Slider*);
void InsertButton(CabbageGUIClass &cAttr);
void InsertSourceButton(CabbageGUIClass &cAttr);
void InsertVUMeter(CabbageGUIClass &cAttr);
void InsertCheckBox(CabbageGUIClass &cAttr);
void InsertCsoundOutput(CabbageGUIClass &cAttr);
void InsertMIDIKeyboard(CabbageGUIClass &cAttr);
void InsertXYPad(CabbageGUIClass &cAttr);
void InsertFileButton(CabbageGUIClass &cAttr);
void InsertImage(CabbageGUIClass &cAttr);
void InsertLabel(CabbageGUIClass &cAttr);
void InsertTable(CabbageGUIClass &cAttr);
void InsertMultiTab(CabbageGUIClass &cAttr);
void InsertInfoButton(CabbageGUIClass &cAttr);
void InsertLineSeparator(CabbageGUIClass &cAttr);
void InsertPatternMatrix(CabbageGUIClass &cAttr);
void InsertSnapshot(CabbageGUIClass &cAttr);
void InsertPVSViewer(CabbageGUIClass &cAttr);
void InsertTransport(CabbageGUIClass &cAttr);
void buttonClicked(Button*);
void buttonStateChanged(Button*);
void showInsertControlsMenu(int x, int y);
void actionListenerCallbackForWidgets(const String message);
void insertScoreStatementText(Table *table, bool overwrite);
void restoreParametersFromPresets(XmlElement* xmlData);
void savePresetsFromParameters(File selectedFile, String mode);
void refreshDiskReadingGUIControls(String typeOfControl);
void updateGUIControls();
void timerCallback();
bool LOCKED;
void insertComponentsFromCabbageText(StringArray text, bool useOffset);
// void insertComponentsFromCabbageTextArray(StringArray text, bool plant);
Array<int> lineNumbers;
Array<int> plantLineNumbers;
int currentLineNumber;
File SnapShotFile;
String presetFileText;
String tempPlantText;
void actionListenerCallback (const String& message);
int zero_dbfs;
StringArray tempArray;
StringArray pastEvents;
Array<Rectangle <int> > boundsForDuplicatedCtrls;
//CabbagePluginAudioProcessor* filter;
CabbagePluginAudioProcessor* getFilter() const
{
return static_cast <CabbagePluginAudioProcessor*> (getAudioProcessor());
}
bool keyStateChanged(bool onoff){
keyIsPressed = onoff;
return false;
}
bool keyIsPressed;
bool isMouseDown;
void positionComponentWithinPlant(String type, int idx, float left, float top, float width, float height, Component *layout, Component *control);
//ScopedPointer<CabbagePlantWindow> subPatch;
OwnedArray<CabbageButton> plantButton;
OwnedArray<CabbagePlantWindow> subPatch;
ScopedPointer<InfoWindow> infoWindow;
void setPositionOfComponent(float x, float y, float width, float height, Component* comp, String reltoplant);
void createfTableData(Table* table, bool sendToCsound);
bool keyPressed(const juce::KeyPress &,Component *);
void updateSizesAndPositionsOfComponents(int newLine = 0);
void deleteComponents();
void duplicateComponents();
void populateLineNumberArray(StringArray csdArray);
void addToRepository(String entryName);
void convertIntoPlant();
void breakUpPlant();
void InsertGroupBox(CabbageGUIClass &cAttr);
void comboBoxChanged (ComboBox* combo);
void InsertComboBox(CabbageGUIClass &cAttr);
void InsertSoundfiler(CabbageGUIClass &cAttr);
void InsertDirectoryList(CabbageGUIClass &cAttr);
void SetupWindow(CabbageGUIClass &cAttr);
void InsertSlider(CabbageGUIClass &cAttr);
void InsertTextEditor(CabbageGUIClass &cAttr);
void sliderValueChanged (Slider*);
void InsertButton(CabbageGUIClass &cAttr);
void InsertCheckBox(CabbageGUIClass &cAttr);
void InsertCsoundOutput(CabbageGUIClass &cAttr);
void InsertMIDIKeyboard(CabbageGUIClass &cAttr);
void InsertXYPad(CabbageGUIClass &cAttr);
void InsertFileButton(CabbageGUIClass &cAttr);
void InsertRecordButton(CabbageGUIClass &cAttr);
void InsertImage(CabbageGUIClass &cAttr);
void InsertLabel(CabbageGUIClass &cAttr);
void InsertTable(CabbageGUIClass &cAttr);
void InsertMultiTab(CabbageGUIClass &cAttr);
void InsertInfoButton(CabbageGUIClass &cAttr);
void InsertLineSeparator(CabbageGUIClass &cAttr);
void InsertPatternMatrix(CabbageGUIClass &cAttr);
void InsertSnapshot(CabbageGUIClass &cAttr);
void InsertTransport(CabbageGUIClass &cAttr);
void InsertPopupMenu(CabbageGUIClass &cAttr);
void InsertGenTable(CabbageGUIClass &cAttr);
void InsertTextbox(CabbageGUIClass &cAttr);
void InsertNumberBox(CabbageGUIClass &cAttr);
void buttonClicked(Button*);
void mouseMove(const MouseEvent& event);
void mouseDown(const MouseEvent& event);
void mouseUp(const MouseEvent& event);
void buttonStateChanged(Button*);
void showInsertControlsMenu(int x, int y);
void insertScoreStatementText(Table *table, bool overwrite);
void restoreParametersFromPresets(XmlElement* xmlData);
void savePresetsFromParameters(File selectedFile, String mode);
void refreshDiskReadingGUIControls(String typeOfControl);
void updatefTableData(GenTable* table);
int mouseX, mouseY;
bool LOCKED;
void insertComponentsFromCabbageText(StringArray text, bool useOffset);
Array<int> lineNumbers;
Array<int> plantLineNumbers;
int currentLineNumber;
File SnapShotFile;
String presetFileText;
String tempPlantText;
void actionListenerCallback (const String& message);
int zero_dbfs;
StringArray tempArray;
StringArray pastEvents;
Array <float, CriticalSection> tableValues;
AudioSampleBuffer tableBuffer;
ScopedPointer<Viewport> viewport;
ScopedPointer<CabbageViewportComponent> viewportComponent;
bool keyStateChanged(bool onoff)
{
keyIsPressed = onoff;
return false;
}
bool keyIsPressed;
bool isMouseDown;
bool showScrollbars;
void positionComponentWithinPlant(String type, float left, float top, float width, float height, Component *layout, Component *control);
//ScopedPointer<CabbagePlantWindow> subPatch;
OwnedArray<CabbageButton> plantButton;
ScopedPointer<InfoWindow> infoWindow;
#ifdef Cabbage_GUI_Editor
ScopedPointer<CabbageMainPanel> componentPanel;
ScopedPointer<ComponentLayoutEditor> layoutEditor;
ScopedPointer<CabbageMainPanel> componentPanel;
ScopedPointer<ComponentLayoutEditor> layoutEditor;
#else
ScopedPointer<Component> componentPanel;
ScopedPointer<Component> componentPanel;
#endif
ScopedPointer<MidiKeyboardComponent> midiKeyboard;
ScopedPointer<LookAndFeel> feely;
Array<float> incomingValues;
ComponentBoundsConstrainer resizeLimits;
AudioPlayHead::CurrentPositionInfo hostInfo;
void changeListenerCallback (ChangeBroadcaster *source);
Colour formColour, fontColour;
String authorText;
String formPic;
float inValue;
int xyPadIndex;
ScopedPointer<CabbageLookAndFeel> lookAndFeel;
ScopedPointer<CabbageLookAndFeelBasic> basicLookAndFeel;
ScopedPointer<Label> debugLabel;
StringArray scoreEvents;
ScopedPointer<MidiKeyboardComponent> midiKeyboard;
ScopedPointer<LookAndFeel> feely;
ComponentBoundsConstrainer resizeLimits;
AudioPlayHead::CurrentPositionInfo hostInfo;
void changeListenerCallback (ChangeBroadcaster *source);
Colour formColour, fontColour;
String authorText;
String formPic;
float inValue;
int xyPadIndex;
ScopedPointer<CabbageLookAndFeel> lookAndFeel;
ScopedPointer<CabbageLookAndFeelBasic> basicLookAndFeel;
ScopedPointer<Label> debugLabel;
StringArray scoreEvents;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CabbagePluginAudioProcessorEditor);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CabbagePluginAudioProcessorEditor);
};
@@ -209,17 +257,18 @@ private:
//==============================================================================
class CabbageCornerResizer : public ResizableCornerComponent
{
CabbagePluginAudioProcessorEditor* editor;
CabbagePluginAudioProcessorEditor* editor;
public:
CabbageCornerResizer(CabbagePluginAudioProcessorEditor* parent, Component* comp, ComponentBoundsConstrainer *constrainer):
ResizableCornerComponent(comp, constrainer), editor(parent){};
~CabbageCornerResizer(){};
void mouseUp(const MouseEvent &e){
editor->updateSize();
}
CabbageCornerResizer(CabbagePluginAudioProcessorEditor* parent, Component* comp, ComponentBoundsConstrainer *constrainer):
ResizableCornerComponent(comp, constrainer), editor(parent) {};
~CabbageCornerResizer() {};
void mouseUp(const MouseEvent &e)
{
editor->updateSize();
}
};
#endif // __PLUGINEDITOR_H_F4EBBBA1__


+ 1573
- 1043
ports/cabbage/source/Plugin/CabbagePluginProcessor.cpp
File diff suppressed because it is too large
View File


+ 450
- 346
ports/cabbage/source/Plugin/CabbagePluginProcessor.h View File

@@ -27,12 +27,18 @@
#include "../XYPadAutomation.h"
#include "../CabbageMessageSystem.h"
#include "../Soundfiler.h"
#include "CabbageGenericAudioProcessorEditor.h"
#include "CabbageGenericAudioProcessorEditor.h"
#include "../CabbageLookAndFeel.h"
#ifndef Cabbage_No_Csound
#include <csound.hpp>
#include "cwindow.h"
#ifdef AndroidBuild
#include "AndroidCsound.hpp"
#else
#include <csound.hpp>
#endif
#include "csdl.h"
//#include "cwindow.h"
#include "../csPerfThread.hpp"
#endif
@@ -40,7 +46,11 @@
//#include "../Editor/CabbageEditorWindow.h"
//#endif
#define CABBAGE_VERSION "Cabbage v0.5.07 Alpha"
#ifdef Cabbage64Bit
#define CABBAGE_VERSION "Cabbage(64bit) v0.5.13 Alpha"
#else
#define CABBAGE_VERSION "Cabbage(32bit) v0.5.13 Alpha"
#endif
#define AUDIO_PLUGIN 1
#define EXTERNAL_PLUGIN 2
@@ -50,135 +60,179 @@
class CsoundCodeEditor;
#endif
extern CabbageLookAndFeel* lookAndFeel;
extern CabbageLookAndFeelBasic* lookAndFeelBasic;
#if defined(BUILD_DEBUGGER) && !defined(Cabbage_No_Csound)
#include <csdebug.h>
#endif
//==============================================================================
// CabbagePluginAudioProcessor definition
//==============================================================================
class CabbagePluginAudioProcessor : public AudioProcessor,
public CabbageUtils,
public ChangeBroadcaster,
public Timer,
public ActionBroadcaster,
public ChangeListener
public CabbageUtils,
public ChangeBroadcaster,
public Timer,
public ActionBroadcaster,
public ChangeListener
{
//==============================================================================
protected:
File csdFile;
int masterCounter;
String filename;
String pluginName;
bool csoundStatus;
int csCompileResult;
void timerCallback();
String csoundOutput;
void changeListenerCallback(ChangeBroadcaster *source);
String changeMessageType;
bool guiON;
int currentLine;
bool xyAutosCreated;
bool updateTable;
Array<int> tableNumbers;
AudioSourceChannelInfo soundfilerChannelData;
AudioPlayHead::CurrentPositionInfo hostInfo;
int soundFileIndex;
//ScopedPointer<FileLogger> fileLogger;
File logFile;
bool isAutomator;
bool isNativeThreadRunning;
//============== Csound related variables/methods ==============================
File csdFile;
int masterCounter;
String filename;
String pluginName;
bool csoundStatus;
int csCompileResult;
void timerCallback();
String csoundOutput;
String debuggerMessage;
void changeListenerCallback(ChangeBroadcaster *source);
String changeMessageType;
bool guiON;
int currentLine;
bool xyAutosCreated;
bool updateTable;
Array<int> tableNumbers;
AudioPlayHead::CurrentPositionInfo hostInfo;
ScopedPointer<FileLogger> fileLogger;
bool createLog;
File logFile;
bool isAutomator;
bool isWinXP;
bool isNativeThreadRunning;
String csoundDebuggerOutput;
//============== Csound related variables/methods ==============================
#ifndef Cabbage_No_Csound
ScopedPointer<CSOUND_PARAMS> csoundParams;
ScopedPointer<CsoundPerformanceThread> csoundPerfThread;
PVSDATEXT* dataout;
MYFLT cs_scale;
ScopedPointer<Csound> csound; //Csound instance
MYFLT *CSspin, *CSspout; //Csound audio IO pointers
int csndIndex; //Csound sample counter
int csdKsmps;
MYFLT *soundFilerTempVector;
int CSCompResult; //result of Csound performKsmps
controlChannelInfo_s* csoundChanList;
int numCsoundChannels; //number of Csound channels
static void messageCallback(CSOUND *csound, int attr, const char *fmt, va_list args); //message callback function
int pos;
//Csound API functions for deailing with midi input
static int OpenMidiInputDevice(CSOUND * csnd, void **userData, const char *devName);
static int OpenMidiOutputDevice(CSOUND * csnd, void **userData, const char *devName);
static int ReadMidiData(CSOUND *csound, void *userData, unsigned char *mbuf, int nbytes);
static int WriteMidiData(CSOUND *csound, void *userData, const unsigned char *mbuf, int nbytes);
int getNumberCsoundOutChannels(){
return csound->GetNchnls();
}
int getNumberCsoundInChannels(){
//return csound->GetInNchnls();
}
int getCsoundSamplingRate(){
return csound->GetSr();
}
int getCsoundKsmpsSize(){
return csound->GetKsmps();
}
ScopedPointer<CSOUND_PARAMS> csoundParams;
ScopedPointer<CsoundPerformanceThread> csoundPerfThread;
PVSDATEXT* dataout;
MYFLT cs_scale;
#if !defined(AndroidBuild)
ScopedPointer<Csound> csound; //Csound instance
#else
ScopedPointer<AndroidCsound> csound;
#endif
static void YieldCallback(void* data);
void updateCabbageControls();
void sendOutgoingMessagesToCsound();
void sendAudioToCsoundFromSoundFilers(int numSamples);
StringArray debugInfo;
//basic classes that hold all information regarding GUI objects
//guiLayoutControls are not used to send data to Csound, and don't show
//as parameters in a host, guiCtrls do show are parameters, and can send
//channel messages to Csound.
Array<CabbageGUIClass, CriticalSection> guiLayoutCtrls;
Array<CabbageGUIClass, CriticalSection> guiCtrls;
String plantFlag, presetFlag;
String debugMessage;
StringArray debugMessageArray;
String currentLineText;
bool editorReOpened;
OwnedArray<XYPadAutomation, CriticalSection> xyAutomation;
void updateGUIControlsKsmps(int speed);
int guiRefreshRate;
public:
MYFLT *CSspin, *CSspout; //Csound audio IO pointers
int csndIndex; //Csound sample counter
int csdKsmps;
int CSCompResult; //result of Csound performKsmps
controlChannelInfo_s* csoundChanList;
int numCsoundChannels; //number of Csound channels
static void messageCallback(CSOUND *csound, int attr, const char *fmt, va_list args); //message callback function
#if defined(BUILD_DEBUGGER) && !defined(Cabbage_No_Csound)
static void breakpointCallback(CSOUND *csound, debug_bkpt_info_t *bkpt_info, void *udata);
#endif
//Csound API functions for deailing with midi input
static int OpenMidiInputDevice(CSOUND * csnd, void **userData, const char *devName);
static int OpenMidiOutputDevice(CSOUND * csnd, void **userData, const char *devName);
static int ReadMidiData(CSOUND *csound, void *userData, unsigned char *mbuf, int nbytes);
static int WriteMidiData(CSOUND *csound, void *userData, const unsigned char *mbuf, int nbytes);
int getNumberCsoundOutChannels()
{
return csound->GetNchnls();
}
int getNumberCsoundInChannels()
{
//return csound->GetInNchnls();
}
int getCsoundSamplingRate()
{
return csound->GetSr();
}
int getCsoundKsmpsSize()
{
return csound->GetKsmps();
}
#endif
static void YieldCallback(void* data);
void updateCabbageControls();
void sendOutgoingMessagesToCsound();
int ksmpsOffset;
bool CS_DEBUG_MODE;
int pos;
StringArray debugInfo;
//basic classes that hold all information regarding GUI objects
//guiLayoutControls are not used to send data to Csound, and don't show
//as parameters in a host, guiCtrls do show are parameters, and can send
//channel messages to Csound.
Array<CabbageGUIClass, CriticalSection> guiLayoutCtrls;
Array<CabbageGUIClass, CriticalSection> guiCtrls;
String plantFlag, presetFlag;
String debugMessage;
StringArray debugMessageArray;
String currentLineText;
bool editorReOpened;
OwnedArray<XYPadAutomation, CriticalSection> xyAutomation;
void updateGUIControlsKsmps(int speed);
int guiRefreshRate;
#ifdef Cabbage_No_Csound
std::vector<float> temp;
#else
std::vector<MYFLT> temp;
#endif
TimeSliceThread backgroundThread; // the thread that will write our audio data to disk
ScopedPointer<AudioFormatWriter::ThreadedWriter> threadedWriter; // the FIFO used to buffer the incoming data
double sampleRate;
int64 nextSampleNum;
File tempAudioFile;
CriticalSection writerLock;
AudioFormatWriter::ThreadedWriter* volatile activeWriter;
public:
String changeMessage;
Array<int> dirtyControls;
bool CSOUND_DEBUG_MODE;
void setCsoundInstrumentBreakpoint(int instr, int line);
void removeCsoundInstrumentBreakpoint(int instr);
void continueCsoundDebug();
void nextCsoundDebug();
void cleanCsoundDebug();
//==============================================================================
#if defined(Cabbage_Build_Standalone) || (Cabbage_Plugin_Host)
CabbagePluginAudioProcessor(String inputfile, bool guiOnOff, int pluginType);
#else
CabbagePluginAudioProcessor();
CabbagePluginAudioProcessor();
#endif
~CabbagePluginAudioProcessor();
#ifdef Cabbage_Build_Standalone
CsoundCodeEditor* codeEditor;
#endif
bool haveXYAutosBeenCreated(){
return xyAutosCreated;
}
void setHaveXYAutoBeenCreated(bool val){
xyAutosCreated = val;
}
double getTailLengthSeconds(void) const {
return 1;
}
#ifdef Cabbage_Build_Standalone
CsoundCodeEditor* codeEditor;
#endif
int performEntireScore();
void reCompileCsound(File file);
void setupNativePluginEditor();
bool compiledOk()
{
return csCompileResult;
}
bool haveXYAutosBeenCreated()
{
return xyAutosCreated;
}
void setHaveXYAutoBeenCreated(bool val)
{
xyAutosCreated = val;
}
double getTailLengthSeconds(void) const
{
return 1;
}
int performEntireScore();
void startRecording();
void stopRecording();
void reCompileCsound(File file);
void setupNativePluginEditor();
//==============================================================================
void prepareToPlay (double sampleRate, int samplesPerBlock);
void releaseResources();
@@ -199,16 +253,13 @@ public:
bool isOutputChannelStereoPair (int index) const;
bool acceptsMidi() const;
bool producesMidi() const;
Array<CabbagePatternMatrixStepData> patStepMatrix;
StringArray patternNames;
Array<CabbagePatternMatrixPfieldData> patPfieldMatrix;
//Array<int> pField4, pField5, pField6, pField7;
int noSteps;
int noPatterns;
int timeCounter;
int beat;
int patMatrixActive;
float bpm;
//Array<int> pField4, pField5, pField6, pField7;
int noSteps;
int noPatterns;
int timeCounter;
int beat;
int patMatrixActive;
float bpm;
//==============================================================================
int getNumPrograms();
int getCurrentProgram();
@@ -218,265 +269,318 @@ public:
//==============================================================================
void getStateInformation (MemoryBlock& destData);
void setStateInformation (const void* data, int sizeInBytes);
const Array<double, CriticalSection> getTable(int tableNum);
void createGUI(String source, bool refresh);
MidiKeyboardState keyboardState;
//midiBuffers
MidiBuffer midiBuffer;
MidiBuffer midiOutputBuffer;
MidiBuffer ccBuffer;
bool showMIDI;
bool yieldCallbackBool;
int yieldCounter;
bool nativePluginEditor;
CabbageMessageQueue messageQueue;
OwnedArray<CabbageAudioSource, CriticalSection> audioSourcesArray;
void addSoundfilerSource(String filename, StringArray channels);
StringArray scoreEvents;
int averageSampleIndex;
float outputNo1;
int pluginType;
float automationAmp;
int automationParamID;
int pluginCalls, csoundCalls;
//==============================================================================
File getCsoundInputFile(){
return csdFile;
}
inline String getCsoundInputFileText(){
String ret="";
#ifdef Cabbage_Build_Standalone
if(codeEditor)
ret = codeEditor->getAllText();
else
ret = csdFile.loadFileAsString();
#endif
return ret;
}
void updateCsoundFile(String text){
//csdFile.replaceWithText(text);
#ifdef Cabbage_Build_Standalone
//codeEditor->textChanged = true;
codeEditor->setAllText(text);
#endif
}
bool hasTextChanged(){
#ifdef Cabbage_Build_Standalone
if(codeEditor)
return codeEditor->textChanged;
else return false;
#else
return false;
#endif
}
void saveText(){
#ifdef Cabbage_Build_Standalone
codeEditor->textChanged = false;
#endif
}
void setOpcodeDirEnv(){
#ifdef WIN32
//showMessage(getenv("OPCODE6DIR64"));
String opcodeDir = File::getSpecialLocation(File::currentExecutableFile).getParentDirectory().getFullPathName()+"\\CsoundPlugins";
//showMessage(opcodeDir);
if(File(opcodeDir).exists()){
String env = "OPCODE6DIR64="+opcodeDir;
_putenv(env.toUTF8().getAddress());
//showMessage(getenv("OPCODE6DIR64"));
}
#endif
}
void highlightLine(String text){
#ifdef Cabbage_Build_Standalone
codeEditor->highlightLine(text);
#endif
}
String getDebugMessage(){
return debugMessage;
}
void addDebugMessage(String message){
debugMessageArray.add(message);;
}
StringArray getDebugMessageArray(){
return debugMessageArray;
}
void clearDebugMessageArray(){
debugMessageArray.clear();
}
int getCompileStatus(){
return csCompileResult;
}
void clearDebugMessage(){
debugMessage="";
}
void setPluginName(String name){
pluginName = name;
}
String getPluginName(){
return pluginName;
}
StringArray getTableStatement(int tableNum);
const Array<double, CriticalSection> getTable(int tableNum);
const Array<float, CriticalSection> getTableFloats(int tableNum);
void createGUI(String source, bool refresh);
int checkTable(int tableNum);
MidiKeyboardState keyboardState;
//midiBuffers
MidiBuffer midiBuffer;
MidiBuffer midiOutputBuffer;
MidiBuffer ccBuffer;
bool showMIDI;
bool yieldCallbackBool;
int yieldCounter;
bool nativePluginEditor;
CabbageMessageQueue messageQueue;
StringArray scoreEvents;
int averageSampleIndex;
bool stopProcessing;
float outputNo1;
int pluginType;
float automationAmp;
int automationParamID;
int mouseX, mouseY;
int breakCount;
Array<int> breakpointInstruments;
Array<Array <float > > tableArrays;
Array<float> getTableArray(int index){
return tableArrays[index];
}
//==============================================================================
File getCsoundInputFile()
{
return csdFile;
}
void setMidiDebug(bool val){
showMIDI=val;
}
bool getMidiDebug(){
return showMIDI;
}
//======== log information about GUI controls ===============
StringArray logGUIAttributes(CabbageGUIClass cAttr, String type){
StringArray arr;
/*
arr.add(String("----------- ")+type+String(" -----------"));
arr.add(String("Name:")+cAttr.getStringProp("name")+String(", Type:")+cAttr.getStringProp("type")+String(", Caption:")+cAttr.getStringProp("caption")+String(", RelToPlant:")+cAttr.getStringProp("reltoplant")+String(", Plant:")+cAttr.getStringProp("plant"));
arr.add(String("PosX:")+String(cAttr.getNumProp("left"))+String(", PosY:")+String(cAttr.getNumProp("top"))+String(", Width:")+String(cAttr.getNumProp("width"))+String(", Height:")+String(cAttr.getNumProp("height")));
*/
arr.add(String(" "));
//Logger::writeToLog(String("----------- ")+type+String(" -----------"));
//Logger::writeToLog(String("Name:")+cAttr.getStringProp("name")+String(", Type:")+cAttr.getStringProp("type")+String(", Caption:")+cAttr.getStringProp("caption")+String(", RelToPlant:")+cAttr.getStringProp("reltoplant")+String(", Plant:")+cAttr.getStringProp("plant"));
//Logger::writeToLog(String("PosX:")+String(cAttr.getNumProp("left"))+String(", PosY:")+String(cAttr.getNumProp("top"))+String(", Width:")+String(cAttr.getNumProp("width"))+String(", Height:")+String(cAttr.getNumProp("height")));
//Logger::writeToLog(" ");
return arr;
}
inline bool getCsoundStatus(){
return csoundStatus;
}
inline String getCsoundInputFileText()
{
String ret="";
#if defined(Cabbage_Build_Standalone) && !defined(AndroidBuild)
if(codeEditor)
ret = codeEditor->getAllText();
else
ret = csdFile.loadFileAsString();
#endif
return ret;
}
//===========================================================
inline int getGUICtrlsSize(){
return (int)guiCtrls.size();
}
void updateCsoundFile(String text)
{
//csdFile.replaceWithText(text);
#if defined(Cabbage_Build_Standalone) && !defined(AndroidBuild)
codeEditor->setAllText(text);
#endif
}
inline int getGUILayoutCtrlsSize(){
return (int)guiLayoutCtrls.size();
}
int saveEditorFiles()
{
#ifdef Cabbage_Build_Standalone
if(codeEditor)
return codeEditor->saveAllFiles();
#endif
}
inline CabbageGUIClass &getGUILayoutCtrls(int index){
return guiLayoutCtrls.getReference(index);
void saveText()
{
#ifdef Cabbage_Build_Standalone
codeEditor->textChanged = false;
#endif
}
void setOpcodeDirEnv()
{
#ifdef WIN32
//showMessage(getenv("OPCODE6DIR64"));
String opcodeDir = File::getSpecialLocation(File::currentExecutableFile).getParentDirectory().getFullPathName()+"\\CsoundPlugins";
if(!File(opcodeDir).exists())
opcodeDir = String(getenv("CABBAGE_OPCODE_PATH"));
Logger::writeToLog("\n================================\nCabbage opcode plugins are located at:"+opcodeDir);
//showMessage(opcodeDir);
if(File(opcodeDir).exists())
{
String env = "OPCODE6DIR64="+opcodeDir;
_putenv(env.toUTF8().getAddress());
Logger::writeToLog("Current opcodeDir is:"+String(getenv("OPCODE6DIR64")));
}
#endif
}
inline CabbageGUIClass &getGUICtrls(int index){
return guiCtrls.getReference(index);
}
void highlightLine(String text)
{
#if defined(Cabbage_Build_Standalone) && !defined(AndroidBuild)
codeEditor->highlightLine(text);
#endif
}
inline String getChangeMessageType(){
return changeMessageType;
}
String getDebugMessage()
{
return debugMessage;
}
inline String getCsoundOutput(){
return csoundOutput;
}
void addDebugMessage(String message)
{
debugMessageArray.add(message);;
}
inline void setChangeMessageType(String text){
changeMessageType = text;
}
StringArray getDebugMessageArray()
{
return debugMessageArray;
}
inline int getCurrentLine(){
return currentLine;
}
void clearDebugMessageArray()
{
debugMessageArray.clear();
}
inline void setCurrentLine(int line){
currentLine = line;
}
int getCompileStatus()
{
return csCompileResult;
}
inline void setCurrentLineText(String lineText){
currentLineText = lineText;
}
void clearDebugMessage()
{
debugMessage="";
}
String getCurrentLineText(){
return currentLineText;
}
void setPluginName(String name)
{
pluginName = name;
}
void removeGUIComponent(int index, String type);
String getPluginName()
{
return pluginName;
}
Array<Array <float > > tableArrays;
Array<float> getTableArray(int index)
{
return tableArrays[index];
}
void setMidiDebug(bool val)
{
showMIDI=val;
}
bool getMidiDebug()
{
return showMIDI;
}
//======== log information about GUI controls ===============
StringArray logGUIAttributes(CabbageGUIClass cAttr, String type)
{
StringArray arr;
/*
arr.add(String("----------- ")+type+String(" -----------"));
arr.add(String("Name:")+cAttr.getStringProp("name")+String(", Type:")+cAttr.getStringProp("type")+String(", Caption:")+cAttr.getStringProp("caption")+String(", RelToPlant:")+cAttr.getStringProp("reltoplant")+String(", Plant:")+cAttr.getStringProp("plant"));
arr.add(String("PosX:")+String(cAttr.getNumProp("left"))+String(", PosY:")+String(cAttr.getNumProp("top"))+String(", Width:")+String(cAttr.getNumProp("width"))+String(", Height:")+String(cAttr.getNumProp("height")));
*/
arr.add(String(" "));
//Logger::writeToLog(String("----------- ")+type+String(" -----------"));
//Logger::writeToLog(String("Name:")+cAttr.getStringProp("name")+String(", Type:")+cAttr.getStringProp("type")+String(", Caption:")+cAttr.getStringProp("caption")+String(", RelToPlant:")+cAttr.getStringProp("reltoplant")+String(", Plant:")+cAttr.getStringProp("plant"));
//Logger::writeToLog(String("PosX:")+String(cAttr.getNumProp("left"))+String(", PosY:")+String(cAttr.getNumProp("top"))+String(", Width:")+String(cAttr.getNumProp("width"))+String(", Height:")+String(cAttr.getNumProp("height")));
//Logger::writeToLog(" ");
return arr;
}
inline bool getCsoundStatus()
{
return csoundStatus;
}
//===========================================================
inline int getGUICtrlsSize()
{
return (int)guiCtrls.size();
}
inline int getGUILayoutCtrlsSize()
{
return (int)guiLayoutCtrls.size();
}
inline CabbageGUIClass &getGUILayoutCtrls(int index)
{
return guiLayoutCtrls.getReference(index);
}
inline CabbageGUIClass &getGUICtrls(int index)
{
return guiCtrls.getReference(index);
}
inline String getChangeMessageType()
{
return changeMessageType;
}
inline String getCsoundOutput()
{
return csoundOutput;
}
inline String getDebuggerOutput()
{
return csoundDebuggerOutput;
}
inline void setChangeMessageType(String text)
{
changeMessageType = text;
}
inline int getCurrentLine()
{
return currentLine;
}
inline void setCurrentLine(int line)
{
currentLine = line;
}
inline void setCurrentLineText(String lineText)
{
currentLineText = lineText;
}
String getCurrentLineText()
{
return currentLineText;
}
void removeGUIComponent(int index, String type);
#ifndef Cabbage_No_Csound
Csound* getCsound(){
return csound;
}
CSOUND* getCsoundStruct(){
return csound->GetCsound();
}
MYFLT getCSScale(){
return cs_scale;
}
PVSDATEXT* getPVSDataOut(){
return dataout;
}
Csound* getCsound()
{
return csound;
}
CSOUND* getCsoundStruct()
{
return csound->GetCsound();
}
MYFLT getCSScale()
{
return cs_scale;
}
PVSDATEXT* getPVSDataOut()
{
return dataout;
}
#endif
void addLayoutCtrl(CabbageGUIClass cAttr){
guiLayoutCtrls.add(cAttr);
}
void addLayoutCtrl(CabbageGUIClass cAttr)
{
guiLayoutCtrls.add(cAttr);
}
void addGUICtrl(CabbageGUIClass cAttr){
guiCtrls.add(cAttr);
}
void addGUICtrl(CabbageGUIClass cAttr)
{
guiCtrls.add(cAttr);
}
bool isGuiEnabled(){
return guiON;
}
bool isGuiEnabled()
{
return guiON;
}
void setGuiEnabled(bool val);
void setGuiEnabled(bool val);
void addXYAutomater(XYPadAutomation* xyAuto){
xyAutomation.add(xyAuto);
}
void addXYAutomater(XYPadAutomation* xyAuto)
{
xyAutomation.add(xyAuto);
}
XYPadAutomation* getXYAutomater(int index){
return xyAutomation[index];
}
XYPadAutomation* getXYAutomater(int index)
{
return xyAutomation[index];
}
int getXYAutomaterSize(){
return xyAutomation.size();
}
int getXYAutomaterSize()
{
return xyAutomation.size();
}
void removeXYAutomaters(){
xyAutomation.clear();
}
void removeXYAutomaters()
{
xyAutomation.clear();
}
bool silenceInProducesSilenceOut() const{
return true;
}
bool silenceInProducesSilenceOut() const
{
return true;
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CabbagePluginAudioProcessor);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CabbagePluginAudioProcessor);
};
//pecial auotmation only plugin type. Does not output any audio.
//special auotmation only plugin type. Does not output any audio.
#ifdef Cabbage_Host
class CabbagePluginAutomationProcessor : public CabbagePluginAudioProcessor
{
public:
CabbagePluginAutomationProcessor(AudioProcessor* filter, String inputfile, int pluginType):
CabbagePluginAudioProcessor(inputfile, false, pluginType)
{}
~CabbagePluginAutomationProcessor(){}
CabbagePluginAutomationProcessor(AudioProcessor* filter, String inputfile, int pluginType):
CabbagePluginAudioProcessor(inputfile, false, pluginType)
{}
~CabbagePluginAutomationProcessor() {}
};


+ 272
- 113
ports/cabbage/source/Soundfiler.cpp View File

@@ -4,7 +4,7 @@
Cabbage is free software; you can redistribute it
and/or modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
version 2.1 of the License, or (at your option) any later version.

Cabbage is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -19,144 +19,303 @@

#include "Soundfiler.h"

//==============================================================================
// zooming button
//==============================================================================
class ZoomButton : public Component,
public ChangeBroadcaster

{
public:
ZoomButton(String type):Component()
{
setName(type);
}
~ZoomButton() {}

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

void paint(Graphics& g)
{
g.fillAll(Colours::transparentBlack);
g.setColour(Colours::white.withAlpha(.8f));
g.fillEllipse(0, 0, getWidth(), getHeight());
g.setColour(Colours::black);
g.fillRoundedRectangle(getWidth()*.18, getHeight()*.4f, getWidth()*.65, getHeight()*.25, 2);
if(getName()=="zoomIn")
g.fillRoundedRectangle(getWidth()*.38f, getHeight()*.20, getWidth()*.25, getHeight()*.65, 2);
}

};
//==============================================================================
// soundfiler component
// soundfiler display component
//==============================================================================
Soundfiler::Soundfiler(CabbageAudioSource& _audioSource, String fileName, int sr, Colour colour, Colour fontColour)
:cabbageAudioSource(&_audioSource)

Soundfiler::Soundfiler(int sr, Colour col, Colour fcol): thumbnailCache (5),
colour(col), sampleRate(sr),
currentPlayPosition(0),
mouseDownX(0),
mouseUpX(0),
drawWaveform(false),
regionWidth(1),
loopLength(0),
scrubberPosition(0),
fontcolour(fcol),
currentPositionMarker(new DrawableRectangle())
{
formatManager.registerBasicFormats();
thumbnail = new AudioThumbnail(2, formatManager, thumbnailCache);
thumbnail->addChangeListener (this);
//setSize(400, 200);
sampleRate = sr;
addAndMakeVisible(scrollbar = new ScrollBar(false));
scrollbar->setRangeLimits (visibleRange);
//scrollbar->setAutoHide (false);
scrollbar->addListener(this);
currentPositionMarker->setFill (Colours::white.withAlpha (0.85f));
addAndMakeVisible(currentPositionMarker);
addAndMakeVisible(zoomIn = new ZoomButton("zoomIn"));
addAndMakeVisible(zoomOut = new ZoomButton("zoomOut"));
zoomIn->addChangeListener(this);
zoomOut->addChangeListener(this);
}
//==============================================================================
Soundfiler::~Soundfiler()
{
scrollbar->removeListener (this);
thumbnail->removeChangeListener (this);
}
//==============================================================================
void Soundfiler::changeListenerCallback(ChangeBroadcaster *source)
{
ZoomButton* button = dynamic_cast<ZoomButton*>(source);
if(button)
{
if(button->getName()=="zoomIn")
setZoomFactor(jmin(1.0, zoom+=0.1));
else
setZoomFactor(jmax(0.0, zoom-=0.1));
}
repaint();
Logger::writeToLog("soundfiler Change listener:"+String(thumbnail->getTotalLength()));
}
//==============================================================================
void Soundfiler::resized()
{
zoomIn->setBounds(getWidth()-43, getHeight()-40, 20, 20);
zoomOut->setBounds(getWidth()-20, getHeight()-40, 20, 20);
if(scrollbar)
scrollbar->setBounds (getLocalBounds().removeFromBottom (20).reduced (2));
}
//==============================================================================
void Soundfiler::scrollBarMoved (ScrollBar* scrollBarThatHasMoved, double newRangeStart)
{
if (scrollBarThatHasMoved == scrollbar)
setRange (visibleRange.movedToStartAt (newRangeStart));
}

viewport = new Viewport();
Logger::writeToLog("sample Rate:"+String(sr));
waveformDisplay = new WaveformDisplay(*cabbageAudioSource->audioSourceBuffer, sr, colour);
//register a listener callback so that we know when to update our audioSource object
cabbageAudioSource->addChangeListener(this);
void Soundfiler::setFile (const File& file)
{
if (! file.isDirectory())
{

//buffer.clear();
//
//buffer.addFrom(0, 0, tableValues.getRawDataPointer(), tableValues.size());
//buffer.addFrom(1, 0, tableValues.getRawDataPointer(), tableValues.size());
AudioFormatManager format;
format.registerBasicFormats();
//registers wav and aif format (just nescearry one time if you alays use the "getInstance()" method)
AudioFormatReader* reader = format.createReaderFor(file);
//creates a reader for the result file (may file, if the result/opened file is no wav or aif)
if(reader) //if a reader got created
{
AudioSampleBuffer buffer(reader->numChannels, reader->lengthInSamples);
buffer.clear();
buffer.setSize(reader->numChannels, reader->lengthInSamples);
reader->read(&buffer,0, buffer.getNumSamples(), 0, true, true);
setWaveform(buffer, reader->numChannels);
}

playButton = new ImageButton("Play button");
playButton->addListener(this);
addAndMakeVisible(playButton);
skipToStartButton = new ImageButton("Skip to start button");
skipToStartButton->addListener(this);
addAndMakeVisible(skipToStartButton);
skipToEndButton = new ImageButton("Skip to end button");
skipToEndButton->addListener(this);
//addAndMakeVisible(skipToEndButton);
//playButton->setToggleState(false, true);
playButton->setClickingTogglesState(true);
//playButton->setState(Button::buttonDown);
delete reader;

playButton->setImages(false, true, true,
CabbageUtils::drawSoundfilerButton("play_normal", fontColour.toString()), 1.0f, Colours::transparentBlack,
CabbageUtils::drawSoundfilerButton("play_hover", fontColour.toString()), 1.0f, Colours::transparentBlack,
CabbageUtils::drawSoundfilerButton("play_down", fontColour.toString()), 1.0f, Colours::transparentBlack);

skipToStartButton->setImages(false, true, true,
CabbageUtils::drawSoundfilerButton("skip_start_normal", fontColour.toString()), 1.0f, Colours::transparentBlack,
CabbageUtils::drawSoundfilerButton("skip_start_hover", fontColour.toString()), 1.0f, Colours::transparentBlack,
CabbageUtils::drawSoundfilerButton("skip_start_down", fontColour.toString()), 1.0f, Colours::transparentBlack);
// thumbnail->setSource (new FileInputSource (file));
// const Range<double> newRange (0.0, thumbnail->getTotalLength());
// scrollbar->setRangeLimits (newRange);
// setRange (newRange);
}
repaint(0, 0, getWidth(), getHeight());
}

//==============================================================================
void Soundfiler::setWaveform(AudioSampleBuffer buffer, int channels)
{
thumbnail->clear();
repaint();
thumbnail->reset(channels, 44100, buffer.getNumSamples());
//thumbnail->clear();
thumbnail->addBlock(0, buffer, 0, buffer.getNumSamples());
const Range<double> newRange (0.0, thumbnail->getTotalLength());
scrollbar->setRangeLimits (newRange);
setRange (newRange);
setZoomFactor(zoom);
repaint();
Logger::writeToLog("updating waveform");
}

skipToEndButton->setImages(false, true, true,
CabbageUtils::drawSoundfilerButton("skip_end_normal", fontColour.toString()), 1.0f, Colours::transparentBlack,
CabbageUtils::drawSoundfilerButton("skip_end_hover", fontColour.toString()), 1.0f, Colours::transparentBlack,
CabbageUtils::drawSoundfilerButton("skip_end_down", fontColour.toString()), 1.0f, Colours::transparentBlack);
//==============================================================================
void Soundfiler::setZoomFactor (double amount)
{
if (thumbnail->getTotalLength() > 0)
{
const double newScale = jmax (0.001, thumbnail->getTotalLength() * (1.0 - jlimit (0.0, 0.99, amount)));
const double timeAtCentre = xToTime (getWidth() / 2.0f);
setRange (Range<double> (timeAtCentre - newScale * 0.5, timeAtCentre + newScale * 0.5));
}
zoom = amount;
repaint();
}
//==============================================================================
void Soundfiler::setRange(Range<double> newRange)
{
visibleRange = newRange;
scrollbar->setCurrentRange (visibleRange);
repaint();
}
//==============================================================================
void Soundfiler::paint (Graphics& g)
{
g.fillAll (Colours::black);
g.setColour (colour);
if (thumbnail->getTotalLength() > 0.01)
{
//if(GEN01 then draw thumbnail)
Rectangle<int> thumbArea (getLocalBounds());
thumbArea.setHeight(getHeight()-14);
thumbArea.setTop(10.f);
thumbnail->drawChannels(g, thumbArea.reduced (2),
visibleRange.getStart(), visibleRange.getEnd(), .8f);

/*
for(int i=0.f;i<getWidth();i++){
g.setColour (fontcolour);
//float pos = visibleRange.getStart()+i;
//float xPos = (jmax(1, i)/visibleRange.getStart()) / (visibleRange.getLength() * getWidth());
//double round = xToTime(i);

loadFile = new TextButton("Open File");
loadFile->getProperties().set("fontcolour", fontColour.toString());
loopFile = new ToggleButton("Loop");
loopFile->getProperties().set("isRect", 1);
loopFile->getProperties().set("colour", fontColour.toString());
loopFile->getProperties().set("fontcolour", fontColour.toString());
addAndMakeVisible(loopFile);
loadFile->addListener(this);
loopFile->addListener(this);
double round = fabs(xToTime(i));
//Logger::writeToLog(String(round-abs((int)round)));
if(round-abs((int)round)<(0.05*(1-zoom)))
{
String test = CabbageUtils::setDecimalPlaces(xToTime(i), 1);
g.setFont(10);
g.drawFittedText(test, i, 0, 20, 11, Justification::left, 1);
//g.drawVerticalLine(i+1, 5, 10);
}

addAndMakeVisible(loadFile);
//g.drawVerticalLine(i, 5, 10);
}*/


addAndMakeVisible(viewport);
setSize (400, 300);

waveformDisplay->setFile(File(fileName), true);
waveformDisplay->setZoomFactor(1);
//if(regionWidth>1){
g.setColour(colour.contrasting(.5f).withAlpha(.7f));
float zoomFactor = thumbnail->getTotalLength()/visibleRange.getLength();
//regionWidth = (regionWidth=2 ? 2 : regionWidth*zoomFactor)
g.fillRect(timeToX(currentPlayPosition), 10.f, (regionWidth==2 ? 2 : regionWidth*zoomFactor), (float)getHeight()-26.f);
//}

viewport->setViewedComponent(waveformDisplay, false);
viewport->setScrollBarsShown(true, true);
}
else
{
g.setColour(Colours::whitesmoke);
g.setFont (14.0f);
g.drawFittedText ("(No audio file loaded)", getLocalBounds(), Justification::centred, 2);
}
}

//==============================================================================
void Soundfiler::mouseWheelMove (const MouseEvent&, const MouseWheelDetails& wheel)
{
if (thumbnail->getTotalLength() > 0.5)
{
double newStart = visibleRange.getStart() - wheel.deltaX * (visibleRange.getLength()) / 10.0;
newStart = jlimit (0.0, jmax (0.0, thumbnail->getTotalLength() - (visibleRange.getLength())), newStart);

setRange (Range<double> (newStart, newStart + visibleRange.getLength()));

void Soundfiler::changeListenerCallback(ChangeBroadcaster *source)
{
CabbageAudioSource* const cabbageAudio = dynamic_cast <CabbageAudioSource*> (source);
if(cabbageAudio){
waveformDisplay->source = cabbageAudio->audioSourceBuffer;
}
}

void Soundfiler::buttonClicked(Button *button)
{
if(button->getName()=="Play button"){
if(!cabbageAudioSource->isSourcePlaying && cabbageAudioSource->isValidFile){
waveformDisplay->startTimer(100);
//startStop->setButtonText("Stop..");
//startStop->setState(Button::buttonDown);
}
else{
waveformDisplay->stopTimer();
//startStop->setButtonText("Play");
}
cabbageAudioSource->isSourcePlaying=!cabbageAudioSource->isSourcePlaying;
}
else if(button->getName()=="Skip to start button"){
waveformDisplay->rewindToStart();
}
else if(button->getName()=="Skip to end button"){
waveformDisplay->skipForward();
}
else if(button->getName()=="Loop"){
if(cabbageAudioSource->isValidFile)
if(button->getToggleState()==true)
cabbageAudioSource->audioSource->setLooping(true);
else
cabbageAudioSource->audioSource->setLooping(false);
}
else{
FileChooser openFC(String("Open a Cabbage sound file..."), File::nonexistent, String("*.wav;*.mp3"));
if(openFC.browseForFileToOpen())
if(cabbageAudioSource->setFile(openFC.getResult().getFullPathName(), 2)){
waveformDisplay->sampleRate = cabbageAudioSource->sampleRate;
waveformDisplay->setFile(openFC.getResult(), false);
waveformDisplay->setZoomFactor(1);
waveformDisplay->stopTimer();
playButton->setToggleState(false, sendNotification);
}
}
repaint();
}
}
//==============================================================================
void Soundfiler::mouseDown (const MouseEvent& e)
{
Logger::writeToLog("mouseDown soundfiler");

if(!e.mods.isPopupMenu())
{
regionWidth = (1.01-zoom)*1.5;
currentPlayPosition = jmax (0.0, xToTime ((float) e.x));
loopStart = e.x;
loopLength = 0;
repaint();
sendChangeMessage();
}
}
//==============================================================================
void Soundfiler::resized()
void Soundfiler::mouseEnter(const MouseEvent& e)
{
waveformDisplay->setSize(800, getHeight()-40);
viewport->setBounds(0, 0, getWidth(), getHeight()-20);
//startStop->setBounds(0, getHeight()-20, 40, 20);
skipToStartButton->setBounds(90, getHeight()-20, 20, 20);
playButton->setBounds(70, getHeight()-20, 20, 20);
skipToEndButton->setBounds(100, getHeight()-20, 20, 20);
loopFile->setBounds(115, getHeight()-20, 60, 20);
loadFile->setBounds(0, getHeight()-20, 70, 20);
//Logger::writeToLog("mouseOver soundfiler");
//if(thumbnail->getTotalLength()>0.01){
// zoomIn->setVisible(true);
// zoomOut->setVisible(true);
//}
}
//==============================================================================
void Soundfiler::paint (Graphics& g)
void Soundfiler::mouseExit(const MouseEvent& e)
{
g.fillAll(Colours::black);
// zoomIn->setVisible(false);
// zoomOut->setVisible(false);
}
//==============================================================================
void Soundfiler::mouseDrag(const MouseEvent& e)
{

if(this->getLocalBounds().contains(e.getPosition()))
{
if(e.mods.isLeftButtonDown())
{
double zoomFactor = visibleRange.getLength()/thumbnail->getTotalLength();
regionWidth = abs(e.getDistanceFromDragStartX())*zoomFactor;
Logger::writeToLog(String(e.getDistanceFromDragStartX()));
if(e.getDistanceFromDragStartX()<0)
currentPlayPosition = jmax (0.0, xToTime (loopStart+(float)e.getDistanceFromDragStartX()));
float widthInTime = ((float)e.getDistanceFromDragStartX() / (float)getWidth()) * (float)thumbnail->getTotalLength();
loopLength = jmax (0.0, widthInTime*zoomFactor);
}
repaint();
}
}
//==============================================================================
void Soundfiler::setScrubberPos(double pos)
{
currentPositionMarker->setVisible (true);
pos = (pos/(thumbnail->getTotalLength()*sampleRate))*thumbnail->getTotalLength();
currentPositionMarker->setRectangle (Rectangle<float> (timeToX (pos) - 0.75f, 10,
1.5f, (float) (getHeight() - scrollbar->getHeight()-10)));
if(pos<0.5)
setRange (visibleRange.movedToStartAt(0));


if(visibleRange.getEnd()<=thumbnail->getTotalLength())
setRange (visibleRange.movedToStartAt (jmax(0.0, pos - (visibleRange.getLength() / 2.0))));
}
//==============================================================================
void Soundfiler::mouseUp(const MouseEvent& e)
{
sendChangeMessage();
}

+ 59
- 164
ports/cabbage/source/Soundfiler.h View File

@@ -4,7 +4,7 @@
Cabbage is free software; you can redistribute it
and/or modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
version 2.1 of the License, or (at your option) any later version.

Cabbage is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -20,198 +20,93 @@
#ifndef SOUNDFILEWAVEFORM_H
#define SOUNDFILEWAVEFORM_H

#include "JuceHeader.h"
#include "JuceHeader.h"
#include "CabbageUtils.h"
#include "CabbageLookAndFeel.h"

class ZoomButton;
//=================================================================
// display a sound file as a waveform..
//=================================================================
class WaveformDisplay : public Component,
public Timer
class Soundfiler : public Component,
public ChangeBroadcaster,
private ScrollBar::Listener,
public ChangeListener
{
public:
WaveformDisplay(BufferingAudioSource &source, int sr, Colour col):
thumbnailCache (5),
source(&source),
colour(col),
sampleRate(sr),
currentPlayPosition(0),
mouseDownX(0),
mouseUpX(0),
drawWaveform(true),
numOfSamples(0)
{
formatManager.registerBasicFormats();
thumbnail = new AudioThumbnail(512, formatManager, thumbnailCache);
setSize(100, 100);
}
~WaveformDisplay()
{
source = nullptr;
}
void resized()
{
}
void setFile (const File& file, bool firstTime)
{
if(file.existsAsFile()){
if(firstTime){
thumbnail->setSource (new FileInputSource(file));
}
else{
//FileInputStream* inFileStream = new FileInputStream(file); // jatFile is the saved thumbnail file
thumbnail = nullptr;
thumbnail = new AudioThumbnail(512, formatManager, thumbnailCache);
thumbnail->setSource (new FileInputSource(file));
//delete inFileStream;
}
drawWaveform=true;
}
else
drawWaveform = false;

startTime = 0;
endTime = thumbnail->getTotalLength();
repaint();
}
Soundfiler(int sr, Colour col, Colour fcol);
~Soundfiler();

void setZoomFactor (double amount)
double getCurrentPlayPos()
{
if (thumbnail->getTotalLength() > 0)
{
const double newScale = jmax (0.001, thumbnail->getTotalLength() * (1.0 - jlimit (0.0, 0.99, amount)));
const double timeAtCentre = xToTime (getWidth() / 2.0f);
//startTime = timeAtCentre - newScale * 0.5;
//endTime = timeAtCentre + newScale * 0.5;
repaint();
}
return currentPlayPosition;
}

void paint (Graphics& g)
int getCurrentPlayPosInSamples()
{
g.fillAll (Colours::black);
g.setColour (colour);
if(drawWaveform){
if (thumbnail->getTotalLength() > 0)
{
thumbnail->drawChannels (g, getLocalBounds(),
startTime, endTime, 2.0f);
}
else
{
g.setFont (14.0f);
g.drawFittedText ("(No audio file selected)", getLocalBounds(), Justification::centred, 2);
}
g.setColour(colour.brighter(.4f));
g.drawLine(timeToX(currentPlayPosition), 0, timeToX(currentPlayPosition), getHeight(), 2);
}
return currentPlayPosition*sampleRate;
}

void timerCallback()
int getLoopLengthInSamples()
{
Viewport* const viewport = findParentComponentOfClass <Viewport> (); //Get the parent viewport
currentPlayPosition = source->getNextReadPosition()/sampleRate;
if(viewport != nullptr) //Check for nullness
viewport->setViewPosition(jmax(0.f, timeToX(currentPlayPosition)-100), 0);
repaint();
return loopLength*sampleRate;
}

void mouseDown (const MouseEvent& e)
{
if(e.mods.isCommandDown()){
if(e.mods.isLeftButtonDown())
this->setSize(jmin(1000, this->getWidth()+100), getHeight());
else
this->setSize(jmax(400, this->getWidth()-100), getHeight());
Logger::writeToLog("command down");
}
source->setNextReadPosition (jmax (0.0, xToTime ((float) e.x)*sampleRate));
currentPlayPosition = jmax (0.0, xToTime ((float) e.x));
mouseDownX = e.x;
repaint();
}

void mouseDrag(const MouseEvent& e)
{
mouseUpX = e.x;
currentPlayPosition = jmax (0.0, xToTime ((float) e.x));
repaint();
}
void rewindToStart(){
if(source)
source->setNextReadPosition (0);
currentPlayPosition = 0.f;
}
void skipForward(){
currentPlayPosition = currentPlayPosition+1.f;
}
AudioThumbnailCache thumbnailCache;
ScopedPointer<AudioThumbnail> thumbnail;
ScopedPointer<BufferingAudioSource> source;
float sampleRate;

private:
AudioFormatManager formatManager;
int64 numOfSamples;
Colour colour;
int mouseDownX, mouseUpX;
double startTime, endTime;
Rectangle<int> localBounds;
double currentPlayPosition;
bool drawWaveform;

DrawableRectangle currentPositionMarker;
void setScrubberPos(double pos);

float timeToX (const double time) const
{
return getWidth() * (float) ((time - startTime) / (endTime - startTime));
return getWidth() * (float) ((time - visibleRange.getStart()) / (visibleRange.getLength()));
}

double xToTime (const float x) const
{
return (x / getWidth()) * (endTime - startTime) + startTime;
return (x / getWidth()) * (visibleRange.getLength()) + visibleRange.getStart();
}
};


class Soundfiler : public Component,
public Button::Listener,
public ChangeListener
{
public:
Soundfiler(CabbageAudioSource& audioSource, String fileName, int sr, Colour colour, Colour fontcolour);
~Soundfiler(){
cabbageAudioSource->isSourcePlaying = false;
cabbageAudioSource->audioSourceBuffer = nullptr;
cabbageAudioSource->removeAllChangeListeners();
cabbageAudioSource = nullptr;
};
// This is just a standard Juce paint method...
void setZoomFactor (double amount);
void setFile (const File& file);
void mouseWheelMove (const MouseEvent&, const MouseWheelDetails& wheel);
void setWaveform(AudioSampleBuffer buffer, int channels);
void createImage(String filename);

private:
Image img;
//Graphics& graphics;
int imgCount;
Range<double> visibleRange;
double zoom;
ScopedPointer<DrawableRectangle> currentPositionMarker;
ScopedPointer<ScrollBar> scrollbar;
void setRange(Range<double> newRange);
void resized();
void paint (Graphics& g);
void changeListenerCallback(ChangeBroadcaster *source);
void resized();
void buttonClicked(Button *button);
ScopedPointer<WaveformDisplay> waveformDisplay;
ScopedPointer<ImageButton> playButton;
ScopedPointer<ImageButton> skipToStartButton;
ScopedPointer<ImageButton> skipToEndButton;
ScopedPointer<TextButton> loadFile;
ScopedPointer<ToggleButton> loopFile;
ScopedPointer<Viewport> viewport;
CabbageAudioSource* cabbageAudioSource;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Soundfiler);
void mouseDown (const MouseEvent& e);
void mouseUp(const MouseEvent& e);
void mouseEnter(const MouseEvent& e);
void mouseDrag(const MouseEvent& e);
void mouseExit(const MouseEvent& e);
bool reDraw;
double scrubberPosition;
void scrollBarMoved (ScrollBar* scrollBarThatHasMoved, double newRangeStart);
void changeListenerCallback(ChangeBroadcaster *source);
ScopedPointer<ZoomButton> zoomIn, zoomOut;

AudioFormatManager formatManager;
float sampleRate;
float regionWidth;
Image waveformImage;
AudioThumbnailCache thumbnailCache;
ScopedPointer<AudioThumbnail> thumbnail;
Colour colour, fontcolour;
int mouseDownX, mouseUpX;
Rectangle<int> localBounds;
double loopLength;
double loopStart;
double currentPlayPosition;
bool drawWaveform;
};


#endif // SOUNDFILEWAVEFORM_H

+ 1373
- 0
ports/cabbage/source/Table.cpp
File diff suppressed because it is too large
View File


+ 357
- 0
ports/cabbage/source/Table.h View File

@@ -0,0 +1,357 @@
/*
Copyright (C) 20139 Rory Walsh

Cabbage is free software; you can redistribute it
and/or modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

Cabbage is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with Csound; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
*/

#ifndef GENTABLE_H
#define GENTABLE_H

#include "JuceHeader.h"
#include "CabbageUtils.h"
#include "CabbageLookAndFeel.h"

class RoundButton;
class HandleViewer;
class HandleComponent;
class GenTable;

class TableManager : public Component,
private ScrollBar::Listener,
public ChangeListener
{
double zoom;
int currentTableIndex;
var tableConfigList;
int largestTable;
double scrubberPosition;
double scrubberFreq;
bool shouldShowTableButtons;
bool shouldShowZoomButtons;
int mainFooterHeight;

public:
TableManager();
~TableManager(){};
void paint (Graphics& g){
g.fillAll(Colours::transparentBlack);
};
void resized();
void setZoomFactor(double zoom);
void setDrawMode(String mode);
void bringButtonsToFront();
void setAmpRanges(Array<float> ampRange);
void timerCallback();
void setRange(double start, double end);
ScopedPointer<DrawableRectangle> currentPositionMarker;
double getLengthInSamples();
void setScrubberPos(double pos, int tableNum);
void scroll(double newRangeStart);
void addTable(int sr, const String col, int gen, Array<float> ampRange, int ftnumber, ChangeListener* listener);
void setWaveform(AudioSampleBuffer buffer, int ftNumber);
void scrollBarMoved (ScrollBar* scrollBarThatHasMoved, double newRangeStart);
void setWaveform(Array<float, CriticalSection> buffer, int ftNumber, bool updateRange = true);
void enableEditMode(StringArray pFields, int ftnumber);
ScopedPointer<RoundButton> zoomIn, zoomOut;
OwnedArray<RoundButton> tableButtons;
OwnedArray<GenTable> tables;
void showZoomButtons(bool show);
void showTableButtons(bool show);
void changeListenerCallback(ChangeBroadcaster *source);
void bringTableToFront(int ftNumber);
void configTableSizes(var tableConfig);
GenTable* getLargestTable();
GenTable* getTableFromFtNumber(int ftnumber);
};

//=================================================================
// display a sound file as a waveform..
//=================================================================
class GenTable : public Component,
public ChangeBroadcaster,
private ScrollBar::Listener,
public ChangeListener
{
public:
GenTable();
~GenTable();

double getCurrentPlayPos()
{
return currentPlayPosition;
}

int getCurrentPlayPosInSamples()
{
return currentPlayPosition*sampleRate;
}

int getLoopLengthInSamples()
{
return loopLength*sampleRate;
}

void setScrubberPos(double pos);

float timeToX (const double time) const
{
return getWidth() * (float) ((time - visibleRange.getStart()) / (visibleRange.getLength()));
}

double xToTime (const float x) const
{
return (x / getWidth()) * (visibleRange.getLength()) + visibleRange.getStart();
}

void setSampleRange(double pos, double end);
void setZoomFactor (double amount);
void setFile (const File& file);
void mouseWheelMove (const MouseEvent&, const MouseWheelDetails& wheel);
void setWaveform(AudioSampleBuffer buffer);
void enableEditMode(StringArray pFields);
Point<int> tableTopAndHeight;
void setWaveform(Array<float, CriticalSection> buffer, bool updateRange = true);
void createImage(String filename);
void addTable(int sr, const String col, int gen, Array<float> ampRange);
static float ampToPixel(int height, Range<float> minMax, float sampleVal);
static float pixelToAmp(int height, Range<float> minMax, float sampleVal);
Array<double> getPfields();
String changeMessage;
int tableNumber, tableSize, genRoutine, realGenRoutine;
void setRange(Range<double> newRange, bool isScrolling = false);
Range<double> globalRange;
bool isTableOnTop;
ScopedPointer<ScrollBar> scrollbar;
void resized();
Range<double> visibleRange;
int scrollbarReduction;
void showScrollbar(bool show);
int mainFooterHeight, paintFooterHeight;
HandleViewer* getHandleViewer(){ return handleViewer;}
double quantiseSpace;
void setAmpRanges(Array<float> ampRange);
void setXPosition(double pos);
bool drawAsVUMeter;
private:
Image img;
bool shouldScroll;
int normalised;
int imgCount;
Colour fillColour;
float currentWidth;
double zoom;
bool showScroll;
double qsteps;
double numPixelsPerIndex;
ColourGradient gradient;
StringArray pFields;
ScopedPointer<DrawableRectangle> currentPositionMarker;
juce::Rectangle<int> thumbArea;
juce::Rectangle<int> handleViewerRect;
void paint (Graphics& g);
void mouseDown (const MouseEvent& e);
void mouseUp(const MouseEvent& e);
void mouseEnter(const MouseEvent& e);
void mouseDrag(const MouseEvent& e);
void mouseExit(const MouseEvent& e);
bool reDraw;
double scrubberPosition;
void scrollBarMoved (ScrollBar* scrollBarThatHasMoved, double newRangeStart);
void changeListenerCallback(ChangeBroadcaster *source);
ScopedPointer<HandleViewer> handleViewer;
AudioFormatManager formatManager;
double sampleRate;
float regionWidth;
Image waveformImage;
AudioThumbnailCache thumbnailCache;
ScopedPointer<AudioThumbnail> thumbnail;
Colour colour, fontcolour;
int mouseDownX, mouseUpX;
juce::Rectangle<int> localBounds;
double loopLength;
double loopStart;
double currentPlayPosition;
bool drawWaveform;



Array<float, CriticalSection> waveformBuffer;
double visibleLength, visibleStart, visibleEnd, maxAmp;
Range<float> minMax;

Range<float> findMinMax(Array<float, CriticalSection> buffer)
{
float min=buffer[0],max=buffer[0];
for(int i=0; i<buffer.size(); i++)
{
if(buffer[i]>max)
max=buffer[i];
if(buffer[i]<min)
min=buffer[i];
}
return Range<float>(min, max);
}

};

//==============================================================================
// HandleViewer class, holds breakpoint handles
//==============================================================================
class HandleViewer : public Component,
public ActionListener
{
void actionListenerCallback(const String &message);
ScopedPointer<Label> label;
public:
HandleViewer();
~HandleViewer();
ScopedPointer<TextButton> button1;
ScopedPointer<TextButton> button2;
void mouseDown(const MouseEvent& e);
void mouseDrag(const MouseEvent& e);
void positionHandle(const MouseEvent& e);
void repaint(Graphics &g);
void resized();
void addHandle(double x, double y, double width, double height, Colour colour);
void insertHandle(double x, double y, Colour colour);
double getSnapPosition(const double y);
HandleComponent* getPreviousHandle(HandleComponent* thisHandle);
HandleComponent* getNextHandle(HandleComponent* thisHandle);
int getHandleIndex(HandleComponent* thisHandle);
void removeHandle (HandleComponent* thisHandle);
OwnedArray<HandleComponent, CriticalSection> handles;
void fixEdgePoints(int gen);
void showHandles(bool show);
void showLabel(String message);
int handleIndex;
double tableSize;
Range<float> minMax;
Colour colour;
int gen;
bool shouldShowHandles;
GenTable* getParentTable(){
return findParentComponentOfClass <GenTable>();
};

};

//==============================================================================
// Handle class
//==============================================================================
class HandleComponent : public Component,
public ChangeBroadcaster,
public ActionBroadcaster
{
public:
HandleComponent(double xPos, double yPos, int index, bool fixed, int gen, Colour colour);
~HandleComponent();

HandleViewer* getParentComponent();
void paint (Graphics& g);
void removeThisHandle();
void mouseEnter (const MouseEvent& e);
void mouseDown (const MouseEvent& e);
void mouseDrag (const MouseEvent& e);
void mouseUp (const MouseEvent& e);
void mouseExit (const MouseEvent& e);
int index;
int height, width;
int x,y;
void setColour(Colour icolour);
void setRelativePositions(Point<double> point);
HandleViewer* getParentHandleViewer(){
return findParentComponentOfClass <HandleViewer>();
};
HandleComponent* getPreviousHandle();
HandleComponent* getNextHandle();
String changeMessage;
String mouseStatus;
double xPosRelative, yPosRelative;
bool status;
private:
Colour colour;
bool fixed;
ComponentDragger dragger;
int lastX, lastY;
int offsetX, offsetY;
int genRoutine;

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (HandleComponent);
};

//==============================================================================
// round button
//==============================================================================
class RoundButton : public Component,
public ChangeBroadcaster

{
String type;
Colour colour;
int mode;
public:
RoundButton(String _type, Colour _colour):Component()
{
setName(_type);
type = _type;
colour = _colour;
mode = 0;
}
~RoundButton() {}

void mouseDown(const MouseEvent& e)
{
//Logger::writeToLog("Mouse down on round button:"+String(type));
sendChangeMessage();
mode = (mode==1 ? 0 : mode+1);
}

void paint(Graphics& g)
{
//Logger::writeToLog(type);
if(type.contains("zoom"))
{
g.fillAll(Colours::transparentBlack);
g.setColour(Colours::white.withAlpha(.8f));
g.fillEllipse(0, 0, getWidth(), getHeight());
g.setColour(Colours::black);
g.fillRoundedRectangle(getWidth()*.18, getHeight()*.4f, getWidth()*.65, getHeight()*.25, 2);
if(getName()=="zoomIn")
g.fillRoundedRectangle(getWidth()*.38f, getHeight()*.20, getWidth()*.25, getHeight()*.65, 2);
}
else{
g.fillAll(Colours::transparentBlack);
g.setColour(colour);
g.fillEllipse(0, 0, getWidth(), getHeight());
g.setColour(colour.contrasting());
g.drawFittedText(type, 0, 0, getWidth(), getHeight(), Justification::centred, 1);
}
}

int getMode()
{
return mode;
}
};

#endif // SOUNDFILEWAVEFORM_H

+ 460
- 438
ports/cabbage/source/XYPad.cpp
File diff suppressed because it is too large
View File


+ 195
- 188
ports/cabbage/source/XYPad.h View File

@@ -4,7 +4,7 @@
Cabbage is free software; you can redistribute it
and/or modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
version 2.1 of the License, or (at your option) any later version.
Cabbage is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -35,25 +35,25 @@
class XYHandleComponent : public Component
{
public:
XYHandleComponent();
~XYHandleComponent();
XYHandleComponent();
~XYHandleComponent();
class XYCanvas* getParentComponent();
void paint (Graphics& g);
void mouseEnter (const MouseEvent& e);
void mouseDown (const MouseEvent& e);
void mouseDrag (const MouseEvent& e);
class XYCanvas* getParentComponent();
void paint (Graphics& g);
void mouseEnter (const MouseEvent& e);
void mouseDown (const MouseEvent& e);
void mouseDrag (const MouseEvent& e);
private:
ComponentDragger dragger;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (XYHandleComponent);
ComponentDragger dragger;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (XYHandleComponent);
};
/*
============================================================================
XYImages
-------------------------------------------------------------------------
Returns custom images for toggle buttons.
@@ -63,38 +63,40 @@ private:
class XYImages
{
public:
XYImages()
{
}
~XYImages()
{
}
static Image getImage(int imageType, float width, float height)
{
Image img = Image(Image::ARGB, width, height, true);
Graphics g(img);
g.setColour(Colours::white);
Path pathLine, pathBall;
if (imageType == 0) {
pathLine.startNewSubPath(width*0.2, height*0.8);
pathLine.lineTo(width*0.7, height*0.2);
g.strokePath(pathLine, PathStrokeType(width*0.04));
pathBall.addEllipse(width*0.6, height*0.45, width*0.2, width*0.2);
}
else if (imageType == 1) {
pathLine.startNewSubPath(width*0.2, height*0.8);
pathLine.lineTo(width*0.8, height*0.2);
g.strokePath(pathLine, PathStrokeType(width*0.05));
Point<float> pt = pathLine.getPointAlongPath(pathLine.getLength()*0.6);
pathBall.addEllipse(pt.getX()-(width*0.1), pt.getY()-(width*0.1), width*0.2, width*0.2);
}
g.fillPath(pathBall);
return img;
}
XYImages()
{
}
~XYImages()
{
}
static Image getImage(int imageType, float width, float height)
{
Image img = Image(Image::ARGB, width, height, true);
Graphics g(img);
g.setColour(Colours::white);
Path pathLine, pathBall;
if (imageType == 0)
{
pathLine.startNewSubPath(width*0.2, height*0.8);
pathLine.lineTo(width*0.7, height*0.2);
g.strokePath(pathLine, PathStrokeType(width*0.04));
pathBall.addEllipse(width*0.6, height*0.45, width*0.2, width*0.2);
}
else if (imageType == 1)
{
pathLine.startNewSubPath(width*0.2, height*0.8);
pathLine.lineTo(width*0.8, height*0.2);
g.strokePath(pathLine, PathStrokeType(width*0.05));
Point<float> pt = pathLine.getPointAlongPath(pathLine.getLength()*0.6);
pathBall.addEllipse(pt.getX()-(width*0.1), pt.getY()-(width*0.1), width*0.2, width*0.2);
}
g.fillPath(pathBall);
return img;
}
};
@@ -103,7 +105,7 @@ public:
============================================================================
XYToggle
-------------------------------------------------------------------------
Custom toggle button.
@@ -113,17 +115,17 @@ public:
class XYToggle : public ToggleButton
{
public:
XYToggle(int imageType, Colour col);
~XYToggle();
void resized();
void paintButton (Graphics& g, bool isMouseOverButton, bool isButtonDown);
XYToggle(int imageType, Colour col);
~XYToggle();
void resized();
void paintButton (Graphics& g, bool isMouseOverButton, bool isButtonDown);
private:
Image img;
int imageType;
Colour colourWhenOn;
Image img;
int imageType;
Colour colourWhenOn;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (XYToggle);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (XYToggle);
};
@@ -141,15 +143,15 @@ private:
class XYValueDisplay : public Component
{
public:
XYValueDisplay(Colour col);
~XYValueDisplay();
void setValue(String value);
void paint(Graphics& g);
XYValueDisplay(Colour col);
~XYValueDisplay();
void setValue(String value);
void paint(Graphics& g);
private:
Colour colour;
String value;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (XYValueDisplay);
Colour colour;
String value;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (XYValueDisplay);
};
/*
@@ -162,14 +164,14 @@ private:
class XYCanvasBackground : public Component
{
public:
XYCanvasBackground();
~XYCanvasBackground();
void resized();
void paint(Graphics& g);
XYCanvasBackground();
~XYCanvasBackground();
void resized();
void paint(Graphics& g);
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (XYCanvasBackground);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (XYCanvasBackground);
};
/*
@@ -185,78 +187,82 @@ private:
*/
class XYCanvas : public Component,
public MultiTimer
public MultiTimer
{
public:
XYCanvas(Colour ballCol, float xMinimum, float xMaximum, float yMinimum,
float yMaximum);
~XYCanvas();
class XYPad* getParentComponent();
void resized();
void cacheStaticBallImage();
void cacheMovingBallImage();
void paint(Graphics& g);
void mouseEnter (const MouseEvent& e);
void mouseDown (const MouseEvent& e);
void mouseDrag (const MouseEvent& e);
void mouseUp (const MouseEvent& e);
Point<float> checkBounds (Point<float> pt);
void setBallPositionFromXYValues(float xValue, float yValue);
void setBallAndHandleSize(float size);
float getBallX();
float getBallY();
void updatePath();
XYHandleComponent* makeHandle(Point<float> pt);
void setStartHandle(Point<float> pt);
void setEndHandle(Point<float> pt);
void clearHandles();
void setToggleId(int selection);
void useStaticBall(bool useStaticBall);
void startBallPathTimer();
XYCanvas(Colour ballCol, float xMinimum, float xMaximum, float yMinimum,
float yMaximum);
~XYCanvas();
class XYPad* getParentComponent();
void resized();
void cacheStaticBallImage();
void cacheMovingBallImage();
void paint(Graphics& g);
void mouseEnter (const MouseEvent& e);
void mouseDown (const MouseEvent& e);
void mouseDrag (const MouseEvent& e);
void mouseUp (const MouseEvent& e);
Point<float> checkBounds (Point<float> pt);
void setBallPositionFromXYValues(float xValue, float yValue);
void setBallAndHandleSize(float size);
float getBallX();
float getBallY();
void updatePath();
XYHandleComponent* makeHandle(Point<float> pt);
void setStartHandle(Point<float> pt);
void setEndHandle(Point<float> pt);
void clearHandles();
void setToggleId(int selection);
void useStaticBall(bool useStaticBall);
void startBallPathTimer();
private:
Image bgImage, staticBallImage, movingBallImage;
float ballX, ballY;
float ballSize, handleSize;
float yMax, xMax, yMin, xMin, xRange, yRange;
Colour ballColour;
Path path;
float pathOpacity, pathThickness, ballLineOpacity;
int toggleId;
bool paintStaticBall;
OwnedArray<XYHandleComponent> handles;
void timerCallback(int id)
{
//This reduces the opacity that is used to paint the path and ball lines. It will
//give it a fade out effect.
// Path
if (id == 1) {
pathOpacity -= 0.1;
pathThickness -= 0.1;
if (toggleId == 0) {
if (pathOpacity <= 0)
stopTimer(1);
}
else if (toggleId == 1) {
if (pathOpacity <= 0.4)
stopTimer(1);
}
//repaint(); //gets repainted anyway
}
// Ball lines
else if (id == 2) {
ballLineOpacity -= 0.1;
if (ballLineOpacity <= 0)
stopTimer(2);
repaint();
}
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (XYCanvas);
Image bgImage, staticBallImage, movingBallImage;
float ballX, ballY;
float ballSize, handleSize;
float yMax, xMax, yMin, xMin, xRange, yRange;
Colour ballColour;
Path path;
float pathOpacity, pathThickness, ballLineOpacity;
int toggleId;
bool paintStaticBall;
OwnedArray<XYHandleComponent> handles;
void timerCallback(int id)
{
//This reduces the opacity that is used to paint the path and ball lines. It will
//give it a fade out effect.
// Path
if (id == 1)
{
pathOpacity -= 0.1;
pathThickness -= 0.1;
if (toggleId == 0)
{
if (pathOpacity <= 0)
stopTimer(1);
}
else if (toggleId == 1)
{
if (pathOpacity <= 0.4)
stopTimer(1);
}
//repaint(); //gets repainted anyway
}
// Ball lines
else if (id == 2)
{
ballLineOpacity -= 0.1;
if (ballLineOpacity <= 0)
stopTimer(2);
repaint();
}
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (XYCanvas);
};
@@ -266,69 +272,70 @@ private:
XYPad
----------------------------------------------------------------------------
This is the main parent class!!
============================================================================
*/
class XYPad : public Component,
public SliderListener,
public ButtonListener,
public ActionBroadcaster
public SliderListener,
public ButtonListener,
public ActionBroadcaster
{
public:
XYPad(XYPadAutomation* xyPadAutomation, String title, int minXValue, int maxXValue,
int minYValue,
int maxYValue,
int numberOfDecimalPlaces,
Colour ballCol,
Colour fontCol,
float initXVal,
float initYVal);
~XYPad();
void resized();
void buttonClicked(Button* button);
void sliderValueChanged(Slider* slider);
void paint (Graphics& g);
void setXYValues(float x, float y);
void setXYValuesFromNormalised(float xNorm, float yNorm);
float getXValueWhenNotAutomating(float x);
float getYValueWhenNotAutomating(float y);
Point<float> checkBounds(float x, float y);
void mouseDown (const MouseEvent& e);
void mouseDrag (const MouseEvent& e);
void mouseUp (const MouseEvent& e);
void mouseEnter (const MouseEvent& e);
void displayXYValues(float xValue, float yValue);
bool isAutomationActive(){
return xyPadAutomation->isAutomationOn;
}
ScopedPointer<Slider> speedSlider;
XYPadAutomation* xyPadAutomation;
XYPad(XYPadAutomation* xyPadAutomation, String title, int minXValue, int maxXValue,
int minYValue,
int maxYValue,
int numberOfDecimalPlaces,
Colour ballCol,
Colour fontCol,
float initXVal,
float initYVal);
~XYPad();
void resized();
void buttonClicked(Button* button);
void sliderValueChanged(Slider* slider);
void paint (Graphics& g);
void setXYValues(float x, float y);
void setXYValuesFromNormalised(float xNorm, float yNorm);
float getXValueWhenNotAutomating(float x);
float getYValueWhenNotAutomating(float y);
Point<float> checkBounds(float x, float y);
void mouseDown (const MouseEvent& e);
void mouseDrag (const MouseEvent& e);
void mouseUp (const MouseEvent& e);
void mouseEnter (const MouseEvent& e);
void displayXYValues(float xValue, float yValue);
bool isAutomationActive()
{
return xyPadAutomation->isAutomationOn;
}
ScopedPointer<Slider> speedSlider;
XYPadAutomation* xyPadAutomation;
private:
ScopedPointer<XYCanvas> canvas;
ScopedPointer<XYCanvasBackground> canvasBackground;
float ballSize;
int speed;
String title, name;
Colour ballColour, fontColour, toggleColour;
float yMax, xMax, yMin, xMin;
float xOut, yOut, xRange, yRange, initX, initY;
int decimalPlaces;
OwnedArray<XYValueDisplay> valueDisplays;
OwnedArray<XYToggle> xyToggles;
ScopedPointer<CabbageLookAndFeel> lookAndFeel;
ScopedPointer<CabbageLookAndFeelBasic> lookAndFeelBasic;
bool canvasHasFocus;
int currentSelectedToggle;
String format;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (XYPad);
ScopedPointer<XYCanvas> canvas;
ScopedPointer<XYCanvasBackground> canvasBackground;
float ballSize;
int speed;
String title, name;
Colour ballColour, fontColour, toggleColour;
float yMax, xMax, yMin, xMin;
float xOut, yOut, xRange, yRange, initX, initY;
int decimalPlaces;
OwnedArray<XYValueDisplay> valueDisplays;
OwnedArray<XYToggle> xyToggles;
ScopedPointer<CabbageLookAndFeel> lookAndFeel;
ScopedPointer<CabbageLookAndFeelBasic> lookAndFeelBasic;
bool canvasHasFocus;
int currentSelectedToggle;
String format;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (XYPad);
};


+ 131
- 121
ports/cabbage/source/XYPadAutomation.cpp View File

@@ -1,17 +1,17 @@
#include "XYPadAutomation.h"
XYPadAutomation::XYPadAutomation()
XYPadAutomation::XYPadAutomation()
{
ballPathDirection = 1;
timerInterval = 50;
ballPathDirection = 1;
timerInterval = 50;
selectedToggle = 0;
speedSliderValue = 0;
isAutomationOn = false;
updateCounter = 0;
paramIndex = 0;
creationCounter = 0;
selectedToggle = 0;
speedSliderValue = 0;
isAutomationOn = false;
updateCounter = 0;
paramIndex = 0;
creationCounter = 0;
}
XYPadAutomation::~XYPadAutomation()
@@ -20,219 +20,229 @@ XYPadAutomation::~XYPadAutomation()
void XYPadAutomation::updateCreationCounter()
{
creationCounter++;
creationCounter++;
}
int XYPadAutomation::getCreationCounter()
{
return creationCounter;
return creationCounter;
}
void XYPadAutomation::setBallSize (float size)
{
ballSize = size;
ballSize = size;
}
void XYPadAutomation::setBoundsForAutomation(Rectangle<int> bounds)
{
availableBounds.setWidth(bounds.getWidth()-ballSize);
availableBounds.setHeight(bounds.getHeight()-ballSize);
}
availableBounds.setWidth(bounds.getWidth()-ballSize);
availableBounds.setHeight(bounds.getHeight()-ballSize);
}
void XYPadAutomation::setBallPath (Path path)
{
AffineTransform transform = AffineTransform::translation((ballSize/2)*-1, (ballSize/2)*-1);
path.applyTransform(transform);
ballPath = path;
AffineTransform transform = AffineTransform::translation((ballSize/2)*-1, (ballSize/2)*-1);
path.applyTransform(transform);
ballPath = path;
}
bool XYPadAutomation::isAutomating()
{
return isAutomationOn;
return isAutomationOn;
}
void XYPadAutomation::setMinMaxValues (float xMinimum, float xMaximum, float yMinimum, float yMaximum)
{
xMin = xMinimum;
yMin = yMinimum;
xMax = xMaximum;
yMax = yMaximum;
xRange = xMax - xMin;
yRange = yMax - yMin;
xMin = xMinimum;
yMin = yMinimum;
xMax = xMaximum;
yMax = yMaximum;
xRange = xMax - xMin;
yRange = yMax - yMin;
xValue = getMinimumXValue();
yValue = getMinimumYValue();
xValue = getMinimumXValue();
yValue = getMinimumYValue();
}
float XYPadAutomation::getMinimumXValue()
{
return xMin;
return xMin;
}
float XYPadAutomation::getMinimumYValue()
{
return yMin;
return yMin;
}
void XYPadAutomation::cancelAutomation()
{
stopTimer();
isAutomationOn = false;
xValueIncrement = yValueIncrement = 0;
stopTimer();
isAutomationOn = false;
xValueIncrement = yValueIncrement = 0;
}
void XYPadAutomation::setInitialSpeedSliderValue ()
{
// Function that calculates the initial speed slider value
float length = ballPath.getLength();
// getting length of parent's diagonal using pythagoras's theorem
int sumOfSquares = (availableBounds.getWidth()*availableBounds.getWidth()) +
(availableBounds.getHeight()*availableBounds.getHeight());
int diagonal = pow(sumOfSquares, 0.5); //square root
speedSliderValue = length / diagonal;
// Function that calculates the initial speed slider value
float length = ballPath.getLength();
// getting length of parent's diagonal using pythagoras's theorem
int sumOfSquares = (availableBounds.getWidth()*availableBounds.getWidth()) +
(availableBounds.getHeight()*availableBounds.getHeight());
int diagonal = pow(sumOfSquares, 0.5); //square root
speedSliderValue = length / diagonal;
}
void XYPadAutomation::updateIncrements()
{
xValueIncrement *= speedValue;
yValueIncrement *= speedValue;
xValueIncrement *= speedValue;
yValueIncrement *= speedValue;
}
void XYPadAutomation::setSpeedSliderValue(float sliderValue)
{
speedSliderValue = sliderValue;
updateCounter = 0; //reset our counter
speedSliderValue = sliderValue;
updateCounter = 0; //reset our counter
}
void XYPadAutomation::beginAutomation(int selectedToggleButton)
{
selectedToggle = selectedToggleButton;
currentPointAlongPath = ballPath.getLength(); //ball begins traversing at the end of the path, rather than the start
setInitialSpeedSliderValue ();
Point<float> startDragPos = ballPath.getPointAlongPath(0);
Point<float> secondPoint = ballPath.getPointAlongPath(1);
Point<float> endDragPos = ballPath.getPointAlongPath(ballPath.getLength());
if (selectedToggle == 0) {
xValueIncrement = ((secondPoint.getX()-startDragPos.getX()) / (float)availableBounds.getWidth()) * xRange;
yValueIncrement = ((secondPoint.getY()-startDragPos.getY()) / (float)availableBounds.getHeight()) * yRange;
yValueIncrement *= -1; //inverting because y axis is also inverted
}
//initialising
xValue = ((endDragPos.getX()/(float)availableBounds.getWidth()) * xRange) + xMin;
yValue = ((1 - (endDragPos.getY()/(float)availableBounds.getHeight())) * yRange) + yMin; //inverting y axis
startTimer (timerInterval);
isAutomationOn = true;
selectedToggle = selectedToggleButton;
currentPointAlongPath = ballPath.getLength(); //ball begins traversing at the end of the path, rather than the start
setInitialSpeedSliderValue ();
Point<float> startDragPos = ballPath.getPointAlongPath(0);
Point<float> secondPoint = ballPath.getPointAlongPath(1);
Point<float> endDragPos = ballPath.getPointAlongPath(ballPath.getLength());
if (selectedToggle == 0)
{
xValueIncrement = ((secondPoint.getX()-startDragPos.getX()) / (float)availableBounds.getWidth()) * xRange;
yValueIncrement = ((secondPoint.getY()-startDragPos.getY()) / (float)availableBounds.getHeight()) * yRange;
yValueIncrement *= -1; //inverting because y axis is also inverted
}
//initialising
xValue = ((endDragPos.getX()/(float)availableBounds.getWidth()) * xRange) + xMin;
yValue = ((1 - (endDragPos.getY()/(float)availableBounds.getHeight())) * yRange) + yMin; //inverting y axis
startTimer (timerInterval);
isAutomationOn = true;
}
void XYPadAutomation::update()
{
if (isAutomating()) {
updateCounter = 0;
if (selectedToggle == 0) { //first automation type
xValue += xValueIncrement*(10*speedSliderValue);
yValue += yValueIncrement*(10*speedSliderValue);
// If a border is hit then the increment value should be reversed...
if (xValue <= xMin) {
xValue = xMin;
xValueIncrement*=-1;
}
else if (xValue >= xMax) {
xValue = xMax;
xValueIncrement*=-1;
}
if (yValue <= yMin) {
yValue = yMin;
yValueIncrement*=-1;
}
else if (yValue >= yMax) {
yValue = yMax;
yValueIncrement*=-1;
}
}
else if (selectedToggle == 1) { //2nd automation type
Point<float> pt = ballPath.getPointAlongPath(currentPointAlongPath, AffineTransform::identity);
xValue = (((pt.getX()/(float)availableBounds.getWidth()) * xRange) + xMin);
yValue = ((pt.getY()/(float)availableBounds.getHeight()) * yRange);
yValue = ((yRange-yValue) + yMin); //inverting and adding yMin
currentPointAlongPath += ballPathDirection*(10*speedSliderValue);
if (currentPointAlongPath > ballPath.getLength()) {
currentPointAlongPath = ballPath.getLength();
ballPathDirection *= -1;
}
else if (currentPointAlongPath < 0) {
currentPointAlongPath = 0;
ballPathDirection *= -1;
}
}
}
if (isAutomating())
{
updateCounter = 0;
if (selectedToggle == 0) //first automation type
{
xValue += xValueIncrement*(10*speedSliderValue);
yValue += yValueIncrement*(10*speedSliderValue);
// If a border is hit then the increment value should be reversed...
if (xValue <= xMin)
{
xValue = xMin;
xValueIncrement*=-1;
}
else if (xValue >= xMax)
{
xValue = xMax;
xValueIncrement*=-1;
}
if (yValue <= yMin)
{
yValue = yMin;
yValueIncrement*=-1;
}
else if (yValue >= yMax)
{
yValue = yMax;
yValueIncrement*=-1;
}
}
else if (selectedToggle == 1) //2nd automation type
{
Point<float> pt = ballPath.getPointAlongPath(currentPointAlongPath, AffineTransform::identity);
xValue = (((pt.getX()/(float)availableBounds.getWidth()) * xRange) + xMin);
yValue = ((pt.getY()/(float)availableBounds.getHeight()) * yRange);
yValue = ((yRange-yValue) + yMin); //inverting and adding yMin
currentPointAlongPath += ballPathDirection*(10*speedSliderValue);
if (currentPointAlongPath > ballPath.getLength())
{
currentPointAlongPath = ballPath.getLength();
ballPathDirection *= -1;
}
else if (currentPointAlongPath < 0)
{
currentPointAlongPath = 0;
ballPathDirection *= -1;
}
}
}
}
void XYPadAutomation::timerCallback()
{
sendChangeMessage();
sendChangeMessage();
}
Point<float> XYPadAutomation::getStartHandle()
{
Point<float> startHandle = ballPath.getPointAlongPath(0);
startHandle.setX(startHandle.getX() + (ballSize/2));
startHandle.setY(startHandle.getY() + (ballSize/2));
Point<float> startHandle = ballPath.getPointAlongPath(0);
startHandle.setX(startHandle.getX() + (ballSize/2));
startHandle.setY(startHandle.getY() + (ballSize/2));
return startHandle;
return startHandle;
}
Point<float> XYPadAutomation::getEndHandle()
{
Point<float> endHandle = ballPath.getPointAlongPath(ballPath.getLength());
endHandle.setX(endHandle.getX() + (ballSize/2));
endHandle.setY(endHandle.getY() + (ballSize/2));
Point<float> endHandle = ballPath.getPointAlongPath(ballPath.getLength());
endHandle.setX(endHandle.getX() + (ballSize/2));
endHandle.setY(endHandle.getY() + (ballSize/2));
return endHandle;
return endHandle;
}
float XYPadAutomation::getXValue()
{
return xValue;
return xValue;
}
float XYPadAutomation::getYValue()
{
return yValue;
return yValue;
}
float XYPadAutomation::getNormalisedXValue()
{
return (xValue-xMin)/xRange;
return (xValue-xMin)/xRange;
}
float XYPadAutomation::getNormalisedYValue()
{
return (yValue-yMin)/yRange;
return (yValue-yMin)/yRange;
}
void XYPadAutomation::setXValue(float value)
{
xValue = value;
sendChangeMessage();
xValue = value;
sendChangeMessage();
}
void XYPadAutomation::setYValue(float value)
{
yValue = value;
sendChangeMessage();
yValue = value;
sendChangeMessage();
}
int XYPadAutomation::getSelectedToggle()
{
return selectedToggle;
return selectedToggle;
}
float XYPadAutomation::getSpeedSliderValue()
{
return speedSliderValue;
return speedSliderValue;
}

+ 63
- 61
ports/cabbage/source/XYPadAutomation.h View File

@@ -4,7 +4,7 @@
Cabbage is free software; you can redistribute it
and/or modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
version 2.1 of the License, or (at your option) any later version.
Cabbage is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -27,69 +27,71 @@
// XYPad Automation class. Allows plugin editor to close while maintining automation
//==============================================================================
class XYPadAutomation : public Timer,
public ChangeBroadcaster
public ChangeBroadcaster
{
public:
XYPadAutomation();
~XYPadAutomation();
void updateCreationCounter();
int getCreationCounter();
void beginAutomation(int selectedToggleButton);
void setBallSize (float size);
void setMinMaxValues (float xMinimum, float xMaximum, float yMinimum, float yMaximum);
float getMinimumXValue();
float getMinimumYValue();
void updateIncrements();
void setInitialSpeedSliderValue ();
void setBallPath (Path path);
void cancelAutomation();
bool isAutomating();
void setSpeedSliderValue(float sliderValue);
void setBoundsForAutomation(Rectangle<int> bounds);
void timerCallback();
Point<float> getStartHandle();
Point<float> getEndHandle();
float getXValue();
float getYValue();
float getNormalisedXValue();
float getNormalisedYValue();
void setXValue(float value);
void setYValue(float value);
int getSelectedToggle();
float getSpeedSliderValue();
String xChannel, yChannel;
void update();
int updateCounter;
int paramIndex;
int creationCounter;
bool isAutomationOn;
float getYRange(){
return yRange;
}
float getXRange(){
return xRange;
}
XYPadAutomation();
~XYPadAutomation();
void updateCreationCounter();
int getCreationCounter();
void beginAutomation(int selectedToggleButton);
void setBallSize (float size);
void setMinMaxValues (float xMinimum, float xMaximum, float yMinimum, float yMaximum);
float getMinimumXValue();
float getMinimumYValue();
void updateIncrements();
void setInitialSpeedSliderValue ();
void setBallPath (Path path);
void cancelAutomation();
bool isAutomating();
void setSpeedSliderValue(float sliderValue);
void setBoundsForAutomation(Rectangle<int> bounds);
void timerCallback();
Point<float> getStartHandle();
Point<float> getEndHandle();
float getXValue();
float getYValue();
float getNormalisedXValue();
float getNormalisedYValue();
void setXValue(float value);
void setYValue(float value);
int getSelectedToggle();
float getSpeedSliderValue();
String xChannel, yChannel;
void update();
int updateCounter;
int paramIndex;
int creationCounter;
bool isAutomationOn;
float getYRange()
{
return yRange;
}
float getXRange()
{
return xRange;
}
private:
float xValue, yValue;
int timerInterval, minTimerInterval;
float xValueIncrement, yValueIncrement;
float speedSliderValue, speedValue;
Rectangle<int> availableBounds;
float ballSize;
float xMin, yMin, xMax, yMax, xRange, yRange;
float xOut, yOut;
int selectedToggle;
Path ballPath;
float currentPointAlongPath, ballPathDirection;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (XYPadAutomation);
float xValue, yValue;
int timerInterval, minTimerInterval;
float xValueIncrement, yValueIncrement;
float speedSliderValue, speedValue;
Rectangle<int> availableBounds;
float ballSize;
float xMin, yMin, xMax, yMax, xRange, yRange;
float xOut, yOut;
int selectedToggle;
Path ballPath;
float currentPointAlongPath, ballPathDirection;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (XYPadAutomation);
};

+ 207
- 180
ports/cabbage/source/csPerfThread.cpp View File

@@ -34,24 +34,25 @@
* Base class for event messages.
*/
class CsoundPerformanceThreadMessage {
protected:
class CsoundPerformanceThreadMessage
{
protected:
CsoundPerformanceThread *pt_;
void SetPaused(int state)
{
pt_->paused = state;
pt_->paused = state;
}
int GetPaused()
{
return pt_->paused;
return pt_->paused;
}
public:
public:
CsoundPerformanceThreadMessage *nxt;
virtual int run() = 0;
CsoundPerformanceThreadMessage(CsoundPerformanceThread *pt)
{
pt_ = pt;
nxt = (CsoundPerformanceThreadMessage*) 0;
pt_ = pt;
nxt = (CsoundPerformanceThreadMessage*) 0;
}
virtual ~CsoundPerformanceThreadMessage()
{
@@ -62,16 +63,17 @@ class CsoundPerformanceThreadMessage {
* Unpause performance
*/
class CsPerfThreadMsg_Play : public CsoundPerformanceThreadMessage {
public:
class CsPerfThreadMsg_Play : public CsoundPerformanceThreadMessage
{
public:
CsPerfThreadMsg_Play(CsoundPerformanceThread *pt)
: CsoundPerformanceThreadMessage(pt)
: CsoundPerformanceThreadMessage(pt)
{
}
int run()
{
SetPaused(0);
return 0;
SetPaused(0);
return 0;
}
~CsPerfThreadMsg_Play()
{
@@ -82,16 +84,17 @@ class CsPerfThreadMsg_Play : public CsoundPerformanceThreadMessage {
* Pause performance
*/
class CsPerfThreadMsg_Pause : public CsoundPerformanceThreadMessage {
public:
class CsPerfThreadMsg_Pause : public CsoundPerformanceThreadMessage
{
public:
CsPerfThreadMsg_Pause(CsoundPerformanceThread *pt)
: CsoundPerformanceThreadMessage(pt)
: CsoundPerformanceThreadMessage(pt)
{
}
int run()
{
SetPaused(1);
return 0;
SetPaused(1);
return 0;
}
~CsPerfThreadMsg_Pause()
{
@@ -102,16 +105,17 @@ class CsPerfThreadMsg_Pause : public CsoundPerformanceThreadMessage {
* Toggle pause mode
*/
class CsPerfThreadMsg_TogglePause : public CsoundPerformanceThreadMessage {
public:
class CsPerfThreadMsg_TogglePause : public CsoundPerformanceThreadMessage
{
public:
CsPerfThreadMsg_TogglePause(CsoundPerformanceThread *pt)
: CsoundPerformanceThreadMessage(pt)
: CsoundPerformanceThreadMessage(pt)
{
}
int run()
{
SetPaused(GetPaused() ? 0 : 1);
return 0;
SetPaused(GetPaused() ? 0 : 1);
return 0;
}
~CsPerfThreadMsg_TogglePause()
{
@@ -122,15 +126,16 @@ class CsPerfThreadMsg_TogglePause : public CsoundPerformanceThreadMessage {
* Stop performance (cannot be continued)
*/
class CsPerfThreadMsg_Stop : public CsoundPerformanceThreadMessage {
public:
class CsPerfThreadMsg_Stop : public CsoundPerformanceThreadMessage
{
public:
CsPerfThreadMsg_Stop(CsoundPerformanceThread *pt)
: CsoundPerformanceThreadMessage(pt)
: CsoundPerformanceThreadMessage(pt)
{
}
int run()
{
return 1;
return 1;
}
~CsPerfThreadMsg_Stop()
{
@@ -147,54 +152,58 @@ class CsPerfThreadMsg_Stop : public CsoundPerformanceThreadMessage {
* *p: array of p-fields, p[0] is p1
*/
class CsPerfThreadMsg_ScoreEvent : public CsoundPerformanceThreadMessage {
private:
class CsPerfThreadMsg_ScoreEvent : public CsoundPerformanceThreadMessage
{
private:
char opcod;
int absp2mode;
int pcnt;
MYFLT *pp;
MYFLT p[10];
public:
public:
CsPerfThreadMsg_ScoreEvent(CsoundPerformanceThread *pt,
int absp2mode, char opcod,
int pcnt, const MYFLT *p)
: CsoundPerformanceThreadMessage(pt)
{
this->opcod = opcod;
this->absp2mode = absp2mode;
this->pcnt = pcnt;
if (pcnt <= 10)
this->pp = &(this->p[0]);
else
this->pp = new MYFLT[(unsigned int) pcnt];
for (int i = 0; i < pcnt; i++)
this->pp[i] = p[i];
: CsoundPerformanceThreadMessage(pt)
{
this->opcod = opcod;
this->absp2mode = absp2mode;
this->pcnt = pcnt;
if (pcnt <= 10)
this->pp = &(this->p[0]);
else
this->pp = new MYFLT[(unsigned int) pcnt];
for (int i = 0; i < pcnt; i++)
this->pp[i] = p[i];
}
int run()
{
CSOUND *csound = pt_->GetCsound();
if (absp2mode && pcnt > 1) {
double p2 = (double) pp[1] - csoundGetScoreTime(csound);
if (p2 < 0.0) {
if (pcnt > 2 && pp[2] >= (MYFLT) 0 &&
(opcod == 'a' || opcod == 'i')) {
pp[2] = (MYFLT) ((double) pp[2] + p2);
if (pp[2] <= (MYFLT) 0)
return 0;
}
p2 = 0.0;
CSOUND *csound = pt_->GetCsound();
if (absp2mode && pcnt > 1)
{
double p2 = (double) pp[1] - csoundGetScoreTime(csound);
if (p2 < 0.0)
{
if (pcnt > 2 && pp[2] >= (MYFLT) 0 &&
(opcod == 'a' || opcod == 'i'))
{
pp[2] = (MYFLT) ((double) pp[2] + p2);
if (pp[2] <= (MYFLT) 0)
return 0;
}
p2 = 0.0;
}
pp[1] = (MYFLT) p2;
}
pp[1] = (MYFLT) p2;
}
if (csoundScoreEvent(csound, opcod, pp, (long) pcnt) != 0)
csoundMessageS(csound, CSOUNDMSG_WARNING,
"WARNING: could not create score event\n");
return 0;
if (csoundScoreEvent(csound, opcod, pp, (long) pcnt) != 0)
csoundMessageS(csound, CSOUNDMSG_WARNING,
"WARNING: could not create score event\n");
return 0;
}
~CsPerfThreadMsg_ScoreEvent()
{
if (pcnt > 10)
delete[] pp;
if (pcnt > 10)
delete[] pp;
}
};
@@ -202,31 +211,32 @@ class CsPerfThreadMsg_ScoreEvent : public CsoundPerformanceThreadMessage {
* Score event message as a string
*/
class CsPerfThreadMsg_InputMessage : public CsoundPerformanceThreadMessage {
private:
class CsPerfThreadMsg_InputMessage : public CsoundPerformanceThreadMessage
{
private:
int len;
char *sp;
char s[128];
public:
public:
CsPerfThreadMsg_InputMessage(CsoundPerformanceThread *pt, const char *s)
: CsoundPerformanceThreadMessage(pt)
: CsoundPerformanceThreadMessage(pt)
{
len = (int) strlen(s);
if (len < 128)
this->sp = &(this->s[0]);
else
this->sp = new char[(unsigned int) (len + 1)];
strcpy(this->sp, s);
len = (int) strlen(s);
if (len < 128)
this->sp = &(this->s[0]);
else
this->sp = new char[(unsigned int) (len + 1)];
strcpy(this->sp, s);
}
int run()
{
csoundInputMessage(pt_->GetCsound(), sp);
return 0;
csoundInputMessage(pt_->GetCsound(), sp);
return 0;
}
~CsPerfThreadMsg_InputMessage()
{
if (len >= 128)
delete[] sp;
if (len >= 128)
delete[] sp;
}
};
@@ -235,20 +245,21 @@ class CsPerfThreadMsg_InputMessage : public CsoundPerformanceThreadMessage {
*/
class CsPerfThreadMsg_SetScoreOffsetSeconds
: public CsoundPerformanceThreadMessage {
private:
: public CsoundPerformanceThreadMessage
{
private:
double timeVal;
public:
public:
CsPerfThreadMsg_SetScoreOffsetSeconds(CsoundPerformanceThread *pt,
double timeVal)
: CsoundPerformanceThreadMessage(pt)
: CsoundPerformanceThreadMessage(pt)
{
this->timeVal = timeVal;
this->timeVal = timeVal;
}
int run()
{
csoundSetScoreOffsetSeconds(pt_->GetCsound(), (MYFLT) timeVal);
return 0;
csoundSetScoreOffsetSeconds(pt_->GetCsound(), (MYFLT) timeVal);
return 0;
}
~CsPerfThreadMsg_SetScoreOffsetSeconds()
{
@@ -265,56 +276,62 @@ class CsPerfThreadMsg_SetScoreOffsetSeconds
int CsoundPerformanceThread::Perform()
{
int retval = 0;
do {
while (firstMessage) {
csoundLockMutex(queueLock);
do {
CsoundPerformanceThreadMessage *msg;
// get oldest message
msg = (CsoundPerformanceThreadMessage*) firstMessage;
if (!msg)
break;
// unlink from FIFO
firstMessage = msg->nxt;
if (!msg->nxt)
lastMessage = (CsoundPerformanceThreadMessage*) 0;
// process and destroy message
retval = msg->run();
delete msg;
} while (!retval);
if (paused)
csoundWaitThreadLock(pauseLock, (size_t) 0);
// mark queue as empty
csoundNotifyThreadLock(flushLock);
csoundUnlockMutex(queueLock);
// if error or end of score, return now
if (retval)
goto endOfPerf;
// if paused, wait until a new message is received, then loop back
if (!paused)
break;
csoundWaitThreadLockNoTimeout(pauseLock);
csoundNotifyThreadLock(pauseLock);
}
if(processcallback != NULL)
processcallback(cdata);
retval = csoundPerformKsmps(csound);
} while (!retval);
endOfPerf:
do
{
while (firstMessage)
{
csoundLockMutex(queueLock);
do
{
CsoundPerformanceThreadMessage *msg;
// get oldest message
msg = (CsoundPerformanceThreadMessage*) firstMessage;
if (!msg)
break;
// unlink from FIFO
firstMessage = msg->nxt;
if (!msg->nxt)
lastMessage = (CsoundPerformanceThreadMessage*) 0;
// process and destroy message
retval = msg->run();
delete msg;
}
while (!retval);
if (paused)
csoundWaitThreadLock(pauseLock, (size_t) 0);
// mark queue as empty
csoundNotifyThreadLock(flushLock);
csoundUnlockMutex(queueLock);
// if error or end of score, return now
if (retval)
goto endOfPerf;
// if paused, wait until a new message is received, then loop back
if (!paused)
break;
csoundWaitThreadLockNoTimeout(pauseLock);
csoundNotifyThreadLock(pauseLock);
}
if(processcallback != NULL)
processcallback(cdata);
retval = csoundPerformKsmps(csound);
}
while (!retval);
endOfPerf:
status = retval;
csoundCleanup(csound);
// delete any pending messages
csoundLockMutex(queueLock);
{
CsoundPerformanceThreadMessage *msg;
msg = (CsoundPerformanceThreadMessage*) firstMessage;
firstMessage = (CsoundPerformanceThreadMessage*) 0;
lastMessage = (CsoundPerformanceThreadMessage*) 0;
while (msg) {
CsoundPerformanceThreadMessage *nxt = msg->nxt;
delete msg;
msg = nxt;
}
CsoundPerformanceThreadMessage *msg;
msg = (CsoundPerformanceThreadMessage*) firstMessage;
firstMessage = (CsoundPerformanceThreadMessage*) 0;
lastMessage = (CsoundPerformanceThreadMessage*) 0;
while (msg)
{
CsoundPerformanceThreadMessage *nxt = msg->nxt;
delete msg;
msg = nxt;
}
}
csoundNotifyThreadLock(flushLock);
csoundUnlockMutex(queueLock);
@@ -322,17 +339,18 @@ int CsoundPerformanceThread::Perform()
return retval;
}
class CsPerfThread_PerformScore {
private:
class CsPerfThread_PerformScore
{
private:
CsoundPerformanceThread *pt;
public:
public:
int Perform()
{
return pt->Perform();
return pt->Perform();
}
CsPerfThread_PerformScore(void *p)
{
pt = (CsoundPerformanceThread*) p;
pt = (CsoundPerformanceThread*) p;
}
~CsPerfThread_PerformScore()
{
@@ -340,14 +358,14 @@ class CsPerfThread_PerformScore {
};
extern "C" {
static uintptr_t csoundPerformanceThread_(void *userData)
{
CsPerfThread_PerformScore p(userData);
// perform the score
int retval = p.Perform();
// return positive value if stopped or end of score, and negative on error
return (uintptr_t) ((unsigned int) retval);
}
static uintptr_t csoundPerformanceThread_(void *userData)
{
CsPerfThread_PerformScore p(userData);
// perform the score
int retval = p.Perform();
// return positive value if stopped or end of score, and negative on error
return (uintptr_t) ((unsigned int) retval);
}
}
void CsoundPerformanceThread::csPerfThread_constructor(CSOUND *csound)
@@ -363,25 +381,27 @@ void CsoundPerformanceThread::csPerfThread_constructor(CSOUND *csound)
status = CSOUND_MEMORY;
queueLock = csoundCreateMutex(0);
if (!queueLock)
return;
return;
pauseLock = csoundCreateThreadLock();
if (!pauseLock)
return;
return;
flushLock = csoundCreateThreadLock();
if (!flushLock)
return;
try {
lastMessage = new CsPerfThreadMsg_Pause(this);
return;
try
{
lastMessage = new CsPerfThreadMsg_Pause(this);
}
catch (std::bad_alloc&) {
return;
catch (std::bad_alloc&)
{
return;
}
processcallback = NULL;
running = 0;
firstMessage = lastMessage;
perfThread = csoundCreateThread(csoundPerformanceThread_, (void*) this);
if (perfThread)
status = 0;
status = 0;
}
// ----------------------------------------------------------------------------
@@ -414,7 +434,7 @@ CsoundPerformanceThread::~CsoundPerformanceThread()
{
// stop performance if it is still running
if (!status)
this->Stop(); // FIXME: should handle memory errors here
this->Stop(); // FIXME: should handle memory errors here
this->Join();
}
@@ -426,16 +446,17 @@ CsoundPerformanceThread::~CsoundPerformanceThread()
void CsoundPerformanceThread::QueueMessage(CsoundPerformanceThreadMessage *msg)
{
if (status) {
delete msg;
return;
if (status)
{
delete msg;
return;
}
csoundLockMutex(queueLock);
// link message into FIFO
if (!lastMessage)
firstMessage = msg;
firstMessage = msg;
else
lastMessage->nxt = msg;
lastMessage->nxt = msg;
lastMessage = msg;
// mark queue as non-empty
csoundWaitThreadLock(flushLock, (size_t) 0);
@@ -489,10 +510,10 @@ void CsoundPerformanceThread::Stop()
*/
void CsoundPerformanceThread::ScoreEvent(int absp2mode, char opcod,
int pcnt, const MYFLT *p)
int pcnt, const MYFLT *p)
{
QueueMessage(new CsPerfThreadMsg_ScoreEvent(this,
absp2mode, opcod, pcnt, p));
absp2mode, opcod, pcnt, p));
}
/**
@@ -527,37 +548,42 @@ int CsoundPerformanceThread::Join()
int retval;
retval = status;
if (perfThread) {
retval = csoundJoinThread(perfThread);
perfThread = (void*) 0;
if (perfThread)
{
retval = csoundJoinThread(perfThread);
perfThread = (void*) 0;
}
// delete any pending messages
{
CsoundPerformanceThreadMessage *msg;
msg = (CsoundPerformanceThreadMessage*) firstMessage;
firstMessage = (CsoundPerformanceThreadMessage*) 0;
lastMessage = (CsoundPerformanceThreadMessage*) 0;
while (msg) {
CsoundPerformanceThreadMessage *nxt = msg->nxt;
delete msg;
msg = nxt;
}
CsoundPerformanceThreadMessage *msg;
msg = (CsoundPerformanceThreadMessage*) firstMessage;
firstMessage = (CsoundPerformanceThreadMessage*) 0;
lastMessage = (CsoundPerformanceThreadMessage*) 0;
while (msg)
{
CsoundPerformanceThreadMessage *nxt = msg->nxt;
delete msg;
msg = nxt;
}
}
// delete all thread locks
if (queueLock) {
csoundDestroyMutex(queueLock);
queueLock = (void*) 0;
if (queueLock)
{
csoundDestroyMutex(queueLock);
queueLock = (void*) 0;
}
if (pauseLock) {
csoundNotifyThreadLock(pauseLock);
csoundDestroyThreadLock(pauseLock);
pauseLock = (void*) 0;
if (pauseLock)
{
csoundNotifyThreadLock(pauseLock);
csoundDestroyThreadLock(pauseLock);
pauseLock = (void*) 0;
}
if (flushLock) {
csoundNotifyThreadLock(flushLock);
csoundDestroyThreadLock(flushLock);
flushLock = (void*) 0;
if (flushLock)
{
csoundNotifyThreadLock(flushLock);
csoundDestroyThreadLock(flushLock);
flushLock = (void*) 0;
}
return retval;
@@ -570,9 +596,10 @@ int CsoundPerformanceThread::Join()
void CsoundPerformanceThread::FlushMessageQueue()
{
if (firstMessage) {
csoundWaitThreadLockNoTimeout(flushLock);
csoundNotifyThreadLock(flushLock);
if (firstMessage)
{
csoundWaitThreadLockNoTimeout(flushLock);
csoundNotifyThreadLock(flushLock);
}
}


+ 32
- 23
ports/cabbage/source/csPerfThread.hpp View File

@@ -76,14 +76,16 @@ int main(int argc, char *argv[])
*/
#ifdef SWIGPYTHON
struct PUBLIC pycallbackdata {
PyObject *func;
PyObject *data;
struct PUBLIC pycallbackdata
{
PyObject *func;
PyObject *data;
};
#endif
class PUBLIC CsoundPerformanceThread {
private:
class PUBLIC CsoundPerformanceThread
{
private:
volatile CsoundPerformanceThreadMessage *firstMessage;
CsoundPerformanceThreadMessage *lastMessage;
CSOUND *csound;
@@ -100,30 +102,37 @@ class PUBLIC CsoundPerformanceThread {
void csPerfThread_constructor(CSOUND *);
void QueueMessage(CsoundPerformanceThreadMessage *);
void (*processcallback)(void *cdata);
public:
int isRunning() { return running;}
public:
int isRunning()
{
return running;
}
#ifdef SWIGPYTHON
PyThreadState *_tstate;
pycallbackdata pydata;
PyThreadState *_tstate;
pycallbackdata pydata;
#endif
/**
* Returns the process callback as a void pointer
*/
void *GetProcessCallback() { return (void *)processcallback; }
/**
* Sets the process callback.
*/
void SetProcessCallback(void (*Callback)(void *), void *cbdata){
processcallback = Callback;
cdata = cbdata;
}
/**
* Returns the process callback as a void pointer
*/
void *GetProcessCallback()
{
return (void *)processcallback;
}
/**
* Sets the process callback.
*/
void SetProcessCallback(void (*Callback)(void *), void *cbdata)
{
processcallback = Callback;
cdata = cbdata;
}
/**
* Returns the Csound instance pointer.
*/
CSOUND *GetCsound()
{
return csound;
return csound;
}
/**
* Returns the current status, zero if still playing, positive if
@@ -132,7 +141,7 @@ class PUBLIC CsoundPerformanceThread {
*/
int GetStatus()
{
return status;
return status;
}
/**
* Continues performance if it was paused.


Loading…
Cancel
Save