mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-02-08 04:20:09 +00:00
Added Value support to the Button's toggle state and TextEditor content. Refactored the atomic operation functions to live inside a class called Atomic, and the byte order functions into a class called ByteOrder.
This commit is contained in:
parent
3ddbc82f9f
commit
18ffeba9da
64 changed files with 3721 additions and 3609 deletions
|
|
@ -50,7 +50,7 @@ Button::Button (const String& name)
|
|||
commandID (0),
|
||||
connectedEdgeFlags (0),
|
||||
buttonState (buttonNormal),
|
||||
isOn (false),
|
||||
lastToggleState (false),
|
||||
clickTogglesState (false),
|
||||
needsToRelease (false),
|
||||
needsRepainting (false),
|
||||
|
|
@ -59,10 +59,13 @@ Button::Button (const String& name)
|
|||
generateTooltip (false)
|
||||
{
|
||||
setWantsKeyboardFocus (true);
|
||||
isOn.addListener (this);
|
||||
}
|
||||
|
||||
Button::~Button()
|
||||
{
|
||||
isOn.removeListener (this);
|
||||
|
||||
if (commandManagerToUse != 0)
|
||||
commandManagerToUse->removeListener (this);
|
||||
|
||||
|
|
@ -98,10 +101,12 @@ const String Button::getTooltip()
|
|||
{
|
||||
const String key (keyPresses.getReference(i).getTextDescription());
|
||||
|
||||
tt << " [";
|
||||
|
||||
if (key.length() == 1)
|
||||
tt << " [" << TRANS("shortcut") << ": '" << key << "']";
|
||||
tt << TRANS("shortcut") << ": '" << key << "']";
|
||||
else
|
||||
tt << " [" << key << ']';
|
||||
tt << key << ']';
|
||||
}
|
||||
|
||||
return tt;
|
||||
|
|
@ -123,17 +128,18 @@ void Button::setConnectedEdges (const int connectedEdgeFlags_) throw()
|
|||
void Button::setToggleState (const bool shouldBeOn,
|
||||
const bool sendChangeNotification)
|
||||
{
|
||||
if (shouldBeOn != isOn)
|
||||
if (shouldBeOn != lastToggleState)
|
||||
{
|
||||
const ComponentDeletionWatcher deletionWatcher (this);
|
||||
|
||||
isOn = shouldBeOn;
|
||||
lastToggleState = shouldBeOn;
|
||||
repaint();
|
||||
|
||||
if (sendChangeNotification)
|
||||
sendClickMessage (ModifierKeys());
|
||||
|
||||
if ((! deletionWatcher.hasBeenDeleted()) && isOn)
|
||||
if ((! deletionWatcher.hasBeenDeleted()) && getToggleState())
|
||||
turnOffOtherButtonsInGroup (sendChangeNotification);
|
||||
}
|
||||
}
|
||||
|
|
@ -154,13 +160,19 @@ bool Button::getClickingTogglesState() const throw()
|
|||
return clickTogglesState;
|
||||
}
|
||||
|
||||
void Button::valueChanged (Value& value)
|
||||
{
|
||||
if (value.refersToSameSourceAs (isOn))
|
||||
setToggleState (isOn.getValue(), true);
|
||||
}
|
||||
|
||||
void Button::setRadioGroupId (const int newGroupId)
|
||||
{
|
||||
if (radioGroupId != newGroupId)
|
||||
{
|
||||
radioGroupId = newGroupId;
|
||||
|
||||
if (isOn)
|
||||
if (getToggleState())
|
||||
turnOffOtherButtonsInGroup (true);
|
||||
}
|
||||
}
|
||||
|
|
@ -294,7 +306,7 @@ void Button::triggerClick()
|
|||
void Button::internalClickCallback (const ModifierKeys& modifiers)
|
||||
{
|
||||
if (clickTogglesState)
|
||||
setToggleState ((radioGroupId != 0) || ! isOn, false);
|
||||
setToggleState ((radioGroupId != 0) || ! getToggleState(), false);
|
||||
|
||||
sendClickMessage (modifiers);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "../keyboard/juce_KeyListener.h"
|
||||
#include "../../../application/juce_ApplicationCommandManager.h"
|
||||
#include "../../../containers/juce_SortedSet.h"
|
||||
#include "../../../containers/juce_Value.h"
|
||||
#include "../windows/juce_TooltipWindow.h"
|
||||
#include "../../../events/juce_Timer.h"
|
||||
class Button;
|
||||
|
|
@ -68,6 +69,7 @@ public:
|
|||
class JUCE_API Button : public Component,
|
||||
public SettableTooltipClient,
|
||||
public ApplicationCommandManagerListener,
|
||||
public Value::Listener,
|
||||
private KeyListener
|
||||
{
|
||||
protected:
|
||||
|
|
@ -139,7 +141,15 @@ public:
|
|||
|
||||
@see setToggleState
|
||||
*/
|
||||
bool getToggleState() const throw() { return isOn; }
|
||||
bool getToggleState() const throw() { return isOn.getValue(); }
|
||||
|
||||
/** Returns the Value object that represents the botton's toggle state.
|
||||
You can use this Value object to connect the button's state to external values or setters,
|
||||
either by taking a copy of the Value, or by using Value::referTo() to make it point to
|
||||
your own Value object.
|
||||
@see getToggleState, Value
|
||||
*/
|
||||
Value& getToggleStateValue() { return isOn; }
|
||||
|
||||
/** This tells the button to automatically flip the toggle state when
|
||||
the button is clicked.
|
||||
|
|
@ -454,7 +464,8 @@ protected:
|
|||
void applicationCommandInvoked (const ApplicationCommandTarget::InvocationInfo&);
|
||||
/** @internal */
|
||||
void applicationCommandListChanged();
|
||||
|
||||
/** @internal */
|
||||
void valueChanged (Value& value);
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
|
|
@ -471,7 +482,8 @@ private:
|
|||
int radioGroupId, commandID, connectedEdgeFlags;
|
||||
ButtonState buttonState;
|
||||
|
||||
bool isOn : 1;
|
||||
Value isOn;
|
||||
bool lastToggleState : 1;
|
||||
bool clickTogglesState : 1;
|
||||
bool needsToRelease : 1;
|
||||
bool needsRepainting : 1;
|
||||
|
|
|
|||
|
|
@ -470,7 +470,7 @@ const String CodeDocument::getTextBetween (const Position& start, const Position
|
|||
|
||||
String result;
|
||||
result.preallocateStorage (end.getPosition() - start.getPosition() + 4);
|
||||
tchar* dest = (tchar*) (const tchar*) result;
|
||||
String::Concatenator concatenator (result);
|
||||
|
||||
const int maxLine = jmin (lines.size() - 1, endLine);
|
||||
|
||||
|
|
@ -482,26 +482,19 @@ const String CodeDocument::getTextBetween (const Position& start, const Position
|
|||
if (i == startLine)
|
||||
{
|
||||
const int index = start.getIndexInLine();
|
||||
len -= index;
|
||||
line->line.substring (index).copyToBuffer (dest, len);
|
||||
dest += len;
|
||||
concatenator.append (line->line.substring (index, len));
|
||||
}
|
||||
else if (i == endLine)
|
||||
{
|
||||
len = end.getIndexInLine();
|
||||
line->line.copyToBuffer (dest, len);
|
||||
dest += len;
|
||||
concatenator.append (line->line.substring (0, len));
|
||||
}
|
||||
else
|
||||
{
|
||||
line->line.copyToBuffer (dest, len);
|
||||
dest += len;
|
||||
concatenator.append (line->line);
|
||||
}
|
||||
}
|
||||
|
||||
// check we preallocated enough space..
|
||||
jassert ((dest - (const tchar*) result) <= end.getPosition() - start.getPosition());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -457,9 +457,9 @@ void Slider::valueChanged (Value& value)
|
|||
setValue (currentValue.getValue(), false, false);
|
||||
}
|
||||
else if (value.refersToSameSourceAs (valueMin))
|
||||
setMinValue (valueMin.getValue(), false, false);
|
||||
setMinValue (valueMin.getValue(), false, false, true);
|
||||
else if (value.refersToSameSourceAs (valueMax))
|
||||
setMaxValue (valueMax.getValue(), false, false);
|
||||
setMaxValue (valueMax.getValue(), false, false, true);
|
||||
}
|
||||
|
||||
double Slider::getValue() const
|
||||
|
|
@ -496,7 +496,7 @@ void Slider::setValue (double newValue,
|
|||
valueBox->hideEditor (true);
|
||||
|
||||
lastCurrentValue = newValue;
|
||||
currentValue = var (newValue);
|
||||
currentValue = newValue;
|
||||
updateText();
|
||||
repaint();
|
||||
|
||||
|
|
@ -546,10 +546,10 @@ void Slider::setMinValue (double newValue, const bool sendUpdateMessage, const b
|
|||
}
|
||||
else
|
||||
{
|
||||
if (allowNudgingOfOtherValues && newValue > (double) currentValue.getValue())
|
||||
if (allowNudgingOfOtherValues && newValue > lastCurrentValue)
|
||||
setValue (newValue, sendUpdateMessage, sendMessageSynchronously);
|
||||
|
||||
newValue = jmin ((double) currentValue.getValue(), newValue);
|
||||
newValue = jmin (lastCurrentValue, newValue);
|
||||
}
|
||||
|
||||
if (lastValueMin != newValue)
|
||||
|
|
@ -586,10 +586,10 @@ void Slider::setMaxValue (double newValue, const bool sendUpdateMessage, const b
|
|||
}
|
||||
else
|
||||
{
|
||||
if (allowNudgingOfOtherValues && newValue < (double) currentValue.getValue())
|
||||
if (allowNudgingOfOtherValues && newValue < lastCurrentValue)
|
||||
setValue (newValue, sendUpdateMessage, sendMessageSynchronously);
|
||||
|
||||
newValue = jmax ((double) currentValue.getValue(), newValue);
|
||||
newValue = jmax (lastCurrentValue, newValue);
|
||||
}
|
||||
|
||||
if (lastValueMax != newValue)
|
||||
|
|
@ -824,7 +824,7 @@ void Slider::paint (Graphics& g)
|
|||
{
|
||||
if (style == Rotary || style == RotaryHorizontalDrag || style == RotaryVerticalDrag)
|
||||
{
|
||||
const float sliderPos = (float) valueToProportionOfLength (currentValue.getValue());
|
||||
const float sliderPos = (float) valueToProportionOfLength (lastCurrentValue);
|
||||
jassert (sliderPos >= 0 && sliderPos <= 1.0f);
|
||||
|
||||
getLookAndFeel().drawRotarySlider (g,
|
||||
|
|
@ -843,9 +843,9 @@ void Slider::paint (Graphics& g)
|
|||
sliderRect.getY(),
|
||||
sliderRect.getWidth(),
|
||||
sliderRect.getHeight(),
|
||||
getLinearSliderPos (currentValue.getValue()),
|
||||
getLinearSliderPos (valueMin.getValue()),
|
||||
getLinearSliderPos (valueMax.getValue()),
|
||||
getLinearSliderPos (lastCurrentValue),
|
||||
getLinearSliderPos (lastValueMin),
|
||||
getLinearSliderPos (lastValueMax),
|
||||
style,
|
||||
*this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,10 +45,10 @@ struct TextAtom
|
|||
uint16 numChars;
|
||||
|
||||
//==============================================================================
|
||||
bool isWhitespace() const throw() { return CharacterFunctions::isWhitespace (atomText[0]); }
|
||||
bool isNewLine() const throw() { return atomText[0] == T('\r') || atomText[0] == T('\n'); }
|
||||
bool isWhitespace() const { return CharacterFunctions::isWhitespace (atomText[0]); }
|
||||
bool isNewLine() const { return atomText[0] == T('\r') || atomText[0] == T('\n'); }
|
||||
|
||||
const String getText (const tchar passwordCharacter) const throw()
|
||||
const String getText (const tchar passwordCharacter) const
|
||||
{
|
||||
if (passwordCharacter == 0)
|
||||
return atomText;
|
||||
|
|
@ -57,7 +57,7 @@ struct TextAtom
|
|||
atomText.length());
|
||||
}
|
||||
|
||||
const String getTrimmedText (const tchar passwordCharacter) const throw()
|
||||
const String getTrimmedText (const tchar passwordCharacter) const
|
||||
{
|
||||
if (passwordCharacter == 0)
|
||||
return atomText.substring (0, numChars);
|
||||
|
|
@ -77,7 +77,7 @@ public:
|
|||
UniformTextSection (const String& text,
|
||||
const Font& font_,
|
||||
const Colour& colour_,
|
||||
const tchar passwordCharacter) throw()
|
||||
const tchar passwordCharacter)
|
||||
: font (font_),
|
||||
colour (colour_),
|
||||
atoms (64)
|
||||
|
|
@ -85,7 +85,7 @@ public:
|
|||
initialiseAtoms (text, passwordCharacter);
|
||||
}
|
||||
|
||||
UniformTextSection (const UniformTextSection& other) throw()
|
||||
UniformTextSection (const UniformTextSection& other)
|
||||
: font (other.font),
|
||||
colour (other.colour),
|
||||
atoms (64)
|
||||
|
|
@ -94,12 +94,12 @@ public:
|
|||
atoms.add (new TextAtom (*(const TextAtom*) other.atoms.getUnchecked(i)));
|
||||
}
|
||||
|
||||
~UniformTextSection() throw()
|
||||
~UniformTextSection()
|
||||
{
|
||||
// (no need to delete the atoms, as they're explicitly deleted by the caller)
|
||||
}
|
||||
|
||||
void clear() throw()
|
||||
void clear()
|
||||
{
|
||||
for (int i = atoms.size(); --i >= 0;)
|
||||
delete getAtom(i);
|
||||
|
|
@ -107,17 +107,17 @@ public:
|
|||
atoms.clear();
|
||||
}
|
||||
|
||||
int getNumAtoms() const throw()
|
||||
int getNumAtoms() const
|
||||
{
|
||||
return atoms.size();
|
||||
}
|
||||
|
||||
TextAtom* getAtom (const int index) const throw()
|
||||
TextAtom* getAtom (const int index) const
|
||||
{
|
||||
return (TextAtom*) atoms.getUnchecked (index);
|
||||
}
|
||||
|
||||
void append (const UniformTextSection& other, const tchar passwordCharacter) throw()
|
||||
void append (const UniformTextSection& other, const tchar passwordCharacter)
|
||||
{
|
||||
if (other.atoms.size() > 0)
|
||||
{
|
||||
|
|
@ -150,7 +150,7 @@ public:
|
|||
}
|
||||
|
||||
UniformTextSection* split (const int indexToBreakAt,
|
||||
const tchar passwordCharacter) throw()
|
||||
const tchar passwordCharacter)
|
||||
{
|
||||
UniformTextSection* const section2 = new UniformTextSection (String::empty,
|
||||
font, colour,
|
||||
|
|
@ -204,96 +204,50 @@ public:
|
|||
return section2;
|
||||
}
|
||||
|
||||
const String getAllText() const throw()
|
||||
void appendAllText (String::Concatenator& concatenator) const
|
||||
{
|
||||
String s;
|
||||
s.preallocateStorage (getTotalLength());
|
||||
|
||||
tchar* endOfString = (tchar*) &(s[0]);
|
||||
for (int i = 0; i < atoms.size(); ++i)
|
||||
concatenator.append (getAtom(i)->atomText);
|
||||
}
|
||||
|
||||
void appendSubstring (String::Concatenator& concatenator,
|
||||
const int startCharacter,
|
||||
const int endCharacter) const
|
||||
{
|
||||
int index = 0;
|
||||
for (int i = 0; i < atoms.size(); ++i)
|
||||
{
|
||||
const TextAtom* const atom = getAtom(i);
|
||||
const TextAtom* const atom = getAtom (i);
|
||||
const int nextIndex = index + atom->numChars;
|
||||
|
||||
memcpy (endOfString, &(atom->atomText[0]), atom->numChars * sizeof (tchar));
|
||||
endOfString += atom->numChars;
|
||||
if (startCharacter < nextIndex)
|
||||
{
|
||||
if (endCharacter <= index)
|
||||
break;
|
||||
|
||||
const int start = jmax (0, startCharacter - index);
|
||||
const int end = jmin (endCharacter - index, atom->numChars);
|
||||
|
||||
if (start < end)
|
||||
concatenator.append (atom->atomText.substring (start, end));
|
||||
}
|
||||
|
||||
index = nextIndex;
|
||||
}
|
||||
|
||||
*endOfString = 0;
|
||||
|
||||
jassert ((endOfString - (tchar*) &(s[0])) <= getTotalLength());
|
||||
return s;
|
||||
}
|
||||
|
||||
const String getTextSubstring (const int startCharacter,
|
||||
const int endCharacter) const throw()
|
||||
{
|
||||
int index = 0;
|
||||
int totalLen = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < atoms.size(); ++i)
|
||||
{
|
||||
const TextAtom* const atom = getAtom (i);
|
||||
const int nextIndex = index + atom->numChars;
|
||||
|
||||
if (startCharacter < nextIndex)
|
||||
{
|
||||
if (endCharacter <= index)
|
||||
break;
|
||||
|
||||
const int start = jmax (0, startCharacter - index);
|
||||
const int end = jmin (endCharacter - index, atom->numChars);
|
||||
jassert (end >= start);
|
||||
|
||||
totalLen += end - start;
|
||||
}
|
||||
|
||||
index = nextIndex;
|
||||
}
|
||||
|
||||
String s;
|
||||
s.preallocateStorage (totalLen + 1);
|
||||
tchar* psz = (tchar*) (const tchar*) s;
|
||||
|
||||
index = 0;
|
||||
|
||||
for (i = 0; i < atoms.size(); ++i)
|
||||
{
|
||||
const TextAtom* const atom = getAtom (i);
|
||||
const int nextIndex = index + atom->numChars;
|
||||
|
||||
if (startCharacter < nextIndex)
|
||||
{
|
||||
if (endCharacter <= index)
|
||||
break;
|
||||
|
||||
const int start = jmax (0, startCharacter - index);
|
||||
const int len = jmin (endCharacter - index, atom->numChars) - start;
|
||||
|
||||
memcpy (psz, ((const tchar*) atom->atomText) + start, len * sizeof (tchar));
|
||||
psz += len;
|
||||
*psz = 0;
|
||||
}
|
||||
|
||||
index = nextIndex;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int getTotalLength() const throw()
|
||||
int getTotalLength() const
|
||||
{
|
||||
int c = 0;
|
||||
int total = 0;
|
||||
|
||||
for (int i = atoms.size(); --i >= 0;)
|
||||
c += getAtom(i)->numChars;
|
||||
total += getAtom(i)->numChars;
|
||||
|
||||
return c;
|
||||
return total;
|
||||
}
|
||||
|
||||
void setFont (const Font& newFont,
|
||||
const tchar passwordCharacter) throw()
|
||||
const tchar passwordCharacter)
|
||||
{
|
||||
if (font != newFont)
|
||||
{
|
||||
|
|
@ -318,7 +272,7 @@ private:
|
|||
|
||||
//==============================================================================
|
||||
void initialiseAtoms (const String& textToParse,
|
||||
const tchar passwordCharacter) throw()
|
||||
const tchar passwordCharacter)
|
||||
{
|
||||
int i = 0;
|
||||
const int len = textToParse.length();
|
||||
|
|
@ -384,7 +338,7 @@ public:
|
|||
//==============================================================================
|
||||
TextEditorIterator (const VoidArray& sections_,
|
||||
const float wordWrapWidth_,
|
||||
const tchar passwordCharacter_) throw()
|
||||
const tchar passwordCharacter_)
|
||||
: indexInText (0),
|
||||
lineY (0),
|
||||
lineHeight (0),
|
||||
|
|
@ -410,7 +364,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
TextEditorIterator (const TextEditorIterator& other) throw()
|
||||
TextEditorIterator (const TextEditorIterator& other)
|
||||
: indexInText (other.indexInText),
|
||||
lineY (other.lineY),
|
||||
lineHeight (other.lineHeight),
|
||||
|
|
@ -428,12 +382,12 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
~TextEditorIterator() throw()
|
||||
~TextEditorIterator()
|
||||
{
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool next() throw()
|
||||
bool next()
|
||||
{
|
||||
if (atom == &tempAtom)
|
||||
{
|
||||
|
|
@ -578,7 +532,7 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
void beginNewLine() throw()
|
||||
void beginNewLine()
|
||||
{
|
||||
atomX = 0;
|
||||
lineY += lineHeight;
|
||||
|
|
@ -630,7 +584,7 @@ public:
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
void draw (Graphics& g, const UniformTextSection*& lastSection) const throw()
|
||||
void draw (Graphics& g, const UniformTextSection*& lastSection) const
|
||||
{
|
||||
if (passwordCharacter != 0 || ! atom->isWhitespace())
|
||||
{
|
||||
|
|
@ -654,7 +608,7 @@ public:
|
|||
|
||||
void drawSelection (Graphics& g,
|
||||
const int selectionStart,
|
||||
const int selectionEnd) const throw()
|
||||
const int selectionEnd) const
|
||||
{
|
||||
const int startX = roundFloatToInt (indexToX (selectionStart));
|
||||
const int endX = roundFloatToInt (indexToX (selectionEnd));
|
||||
|
|
@ -668,7 +622,7 @@ public:
|
|||
void drawSelectedText (Graphics& g,
|
||||
const int selectionStart,
|
||||
const int selectionEnd,
|
||||
const Colour& selectedTextColour) const throw()
|
||||
const Colour& selectedTextColour) const
|
||||
{
|
||||
if (passwordCharacter != 0 || ! atom->isWhitespace())
|
||||
{
|
||||
|
|
@ -704,7 +658,7 @@ public:
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
float indexToX (const int indexToFind) const throw()
|
||||
float indexToX (const int indexToFind) const
|
||||
{
|
||||
if (indexToFind <= indexInText)
|
||||
return atomX;
|
||||
|
|
@ -723,7 +677,7 @@ public:
|
|||
return jmin (atomRight, g.getGlyph (indexToFind - indexInText).getLeft());
|
||||
}
|
||||
|
||||
int xToIndex (const float xToFind) const throw()
|
||||
int xToIndex (const float xToFind) const
|
||||
{
|
||||
if (xToFind <= atomX || atom->isNewLine())
|
||||
return indexInText;
|
||||
|
|
@ -745,7 +699,7 @@ public:
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
bool getCharPosition (const int index, float& cx, float& cy, float& lineHeight_) throw()
|
||||
bool getCharPosition (const int index, float& cx, float& cy, float& lineHeight_)
|
||||
{
|
||||
while (next())
|
||||
{
|
||||
|
|
@ -782,7 +736,7 @@ private:
|
|||
|
||||
const TextEditorIterator& operator= (const TextEditorIterator&);
|
||||
|
||||
void moveToEndOfLastAtom() throw()
|
||||
void moveToEndOfLastAtom()
|
||||
{
|
||||
if (atom != 0)
|
||||
{
|
||||
|
|
@ -796,7 +750,7 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
bool shouldWrap (const float x) const throw()
|
||||
bool shouldWrap (const float x) const
|
||||
{
|
||||
return (x - 0.0001f) >= wordWrapWidth;
|
||||
}
|
||||
|
|
@ -822,7 +776,7 @@ public:
|
|||
const Font& font_,
|
||||
const Colour& colour_,
|
||||
const int oldCaretPos_,
|
||||
const int newCaretPos_) throw()
|
||||
const int newCaretPos_)
|
||||
: owner (owner_),
|
||||
text (text_),
|
||||
insertIndex (insertIndex_),
|
||||
|
|
@ -871,7 +825,7 @@ public:
|
|||
const int endIndex_,
|
||||
const int oldCaretPos_,
|
||||
const int newCaretPos_,
|
||||
const VoidArray& removedSections_) throw()
|
||||
const VoidArray& removedSections_)
|
||||
: owner (owner_),
|
||||
startIndex (startIndex_),
|
||||
endIndex (endIndex_),
|
||||
|
|
@ -920,38 +874,47 @@ public:
|
|||
|
||||
//==============================================================================
|
||||
class TextHolderComponent : public Component,
|
||||
public Timer
|
||||
public Timer,
|
||||
public Value::Listener
|
||||
{
|
||||
TextEditor* const owner;
|
||||
TextEditor& owner;
|
||||
|
||||
TextHolderComponent (const TextHolderComponent&);
|
||||
const TextHolderComponent& operator= (const TextHolderComponent&);
|
||||
|
||||
public:
|
||||
TextHolderComponent (TextEditor* const owner_)
|
||||
TextHolderComponent (TextEditor& owner_)
|
||||
: owner (owner_)
|
||||
{
|
||||
setWantsKeyboardFocus (false);
|
||||
setInterceptsMouseClicks (false, true);
|
||||
|
||||
owner.getTextValue().addListener (this);
|
||||
}
|
||||
|
||||
~TextHolderComponent()
|
||||
{
|
||||
owner.getTextValue().removeListener (this);
|
||||
}
|
||||
|
||||
void paint (Graphics& g)
|
||||
{
|
||||
owner->drawContent (g);
|
||||
owner.drawContent (g);
|
||||
}
|
||||
|
||||
void timerCallback()
|
||||
{
|
||||
owner->timerCallbackInt();
|
||||
owner.timerCallbackInt();
|
||||
}
|
||||
|
||||
const MouseCursor getMouseCursor()
|
||||
{
|
||||
return owner->getMouseCursor();
|
||||
return owner.getMouseCursor();
|
||||
}
|
||||
|
||||
void valueChanged (Value&)
|
||||
{
|
||||
owner.textWasChangedByValue();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1014,6 +977,7 @@ TextEditor::TextEditor (const String& name,
|
|||
keepCursorOnScreen (true),
|
||||
tabKeyUsed (false),
|
||||
menuActive (false),
|
||||
valueTextNeedsUpdating (false),
|
||||
cursorX (0),
|
||||
cursorY (0),
|
||||
cursorHeight (0),
|
||||
|
|
@ -1034,7 +998,7 @@ TextEditor::TextEditor (const String& name,
|
|||
setOpaque (true);
|
||||
|
||||
addAndMakeVisible (viewport = new TextEditorViewport (this));
|
||||
viewport->setViewedComponent (textHolder = new TextHolderComponent (this));
|
||||
viewport->setViewedComponent (textHolder = new TextHolderComponent (*this));
|
||||
viewport->setWantsKeyboardFocus (false);
|
||||
viewport->setScrollBarsShown (false, false);
|
||||
|
||||
|
|
@ -1046,10 +1010,11 @@ TextEditor::~TextEditor()
|
|||
{
|
||||
clearInternal (0);
|
||||
viewport = 0;
|
||||
textHolder = 0;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void TextEditor::newTransaction() throw()
|
||||
void TextEditor::newTransaction()
|
||||
{
|
||||
lastTransactionTime = Time::getApproximateMillisecondCounter();
|
||||
undoManager.beginNewTransaction();
|
||||
|
|
@ -1084,12 +1049,12 @@ void TextEditor::setMultiLine (const bool shouldBeMultiLine,
|
|||
scrollToMakeSureCursorIsVisible();
|
||||
}
|
||||
|
||||
bool TextEditor::isMultiLine() const throw()
|
||||
bool TextEditor::isMultiLine() const
|
||||
{
|
||||
return multiline;
|
||||
}
|
||||
|
||||
void TextEditor::setScrollbarsShown (bool enabled) throw()
|
||||
void TextEditor::setScrollbarsShown (bool enabled)
|
||||
{
|
||||
scrollbarVisible = enabled;
|
||||
|
||||
|
|
@ -1104,7 +1069,7 @@ void TextEditor::setReadOnly (const bool shouldBeReadOnly)
|
|||
enablementChanged();
|
||||
}
|
||||
|
||||
bool TextEditor::isReadOnly() const throw()
|
||||
bool TextEditor::isReadOnly() const
|
||||
{
|
||||
return readOnly || ! isEnabled();
|
||||
}
|
||||
|
|
@ -1114,28 +1079,28 @@ void TextEditor::setReturnKeyStartsNewLine (const bool shouldStartNewLine)
|
|||
returnKeyStartsNewLine = shouldStartNewLine;
|
||||
}
|
||||
|
||||
void TextEditor::setTabKeyUsedAsCharacter (const bool shouldTabKeyBeUsed) throw()
|
||||
void TextEditor::setTabKeyUsedAsCharacter (const bool shouldTabKeyBeUsed)
|
||||
{
|
||||
tabKeyUsed = shouldTabKeyBeUsed;
|
||||
}
|
||||
|
||||
void TextEditor::setPopupMenuEnabled (const bool b) throw()
|
||||
void TextEditor::setPopupMenuEnabled (const bool b)
|
||||
{
|
||||
popupMenuEnabled = b;
|
||||
}
|
||||
|
||||
void TextEditor::setSelectAllWhenFocused (const bool b) throw()
|
||||
void TextEditor::setSelectAllWhenFocused (const bool b)
|
||||
{
|
||||
selectAllTextWhenFocused = b;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
const Font TextEditor::getFont() const throw()
|
||||
const Font TextEditor::getFont() const
|
||||
{
|
||||
return currentFont;
|
||||
}
|
||||
|
||||
void TextEditor::setFont (const Font& newFont) throw()
|
||||
void TextEditor::setFont (const Font& newFont)
|
||||
{
|
||||
currentFont = newFont;
|
||||
scrollToMakeSureCursorIsVisible();
|
||||
|
|
@ -1166,7 +1131,7 @@ void TextEditor::colourChanged()
|
|||
repaint();
|
||||
}
|
||||
|
||||
void TextEditor::setCaretVisible (const bool shouldCaretBeVisible) throw()
|
||||
void TextEditor::setCaretVisible (const bool shouldCaretBeVisible)
|
||||
{
|
||||
caretVisible = shouldCaretBeVisible;
|
||||
|
||||
|
|
@ -1178,19 +1143,19 @@ void TextEditor::setCaretVisible (const bool shouldCaretBeVisible) throw()
|
|||
}
|
||||
|
||||
void TextEditor::setInputRestrictions (const int maxLen,
|
||||
const String& chars) throw()
|
||||
const String& chars)
|
||||
{
|
||||
maxTextLength = jmax (0, maxLen);
|
||||
allowedCharacters = chars;
|
||||
}
|
||||
|
||||
void TextEditor::setTextToShowWhenEmpty (const String& text, const Colour& colourToUse) throw()
|
||||
void TextEditor::setTextToShowWhenEmpty (const String& text, const Colour& colourToUse)
|
||||
{
|
||||
textToShowWhenEmpty = text;
|
||||
colourForTextWhenEmpty = colourToUse;
|
||||
}
|
||||
|
||||
void TextEditor::setPasswordCharacter (const tchar newPasswordCharacter) throw()
|
||||
void TextEditor::setPasswordCharacter (const tchar newPasswordCharacter)
|
||||
{
|
||||
if (passwordCharacter != newPasswordCharacter)
|
||||
{
|
||||
|
|
@ -1252,10 +1217,34 @@ void TextEditor::setText (const String& newText,
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
void TextEditor::textChanged() throw()
|
||||
Value& TextEditor::getTextValue()
|
||||
{
|
||||
if (valueTextNeedsUpdating)
|
||||
{
|
||||
valueTextNeedsUpdating = false;
|
||||
textValue = getText();
|
||||
}
|
||||
|
||||
return textValue;
|
||||
}
|
||||
|
||||
void TextEditor::textWasChangedByValue()
|
||||
{
|
||||
if (textValue.getValueSource().getReferenceCount() > 1)
|
||||
setText (textValue.getValue());
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void TextEditor::textChanged()
|
||||
{
|
||||
updateTextHolderSize();
|
||||
postCommandMessage (textChangeMessageId);
|
||||
|
||||
if (textValue.getValueSource().getReferenceCount() > 1)
|
||||
{
|
||||
valueTextNeedsUpdating = false;
|
||||
textValue = getText();
|
||||
}
|
||||
}
|
||||
|
||||
void TextEditor::returnPressed()
|
||||
|
|
@ -1268,7 +1257,7 @@ void TextEditor::escapePressed()
|
|||
postCommandMessage (escapeKeyMessageId);
|
||||
}
|
||||
|
||||
void TextEditor::addListener (TextEditorListener* const newListener) throw()
|
||||
void TextEditor::addListener (TextEditorListener* const newListener)
|
||||
{
|
||||
jassert (newListener != 0)
|
||||
|
||||
|
|
@ -1276,7 +1265,7 @@ void TextEditor::addListener (TextEditorListener* const newListener) throw()
|
|||
listeners.add (newListener);
|
||||
}
|
||||
|
||||
void TextEditor::removeListener (TextEditorListener* const listenerToRemove) throw()
|
||||
void TextEditor::removeListener (TextEditorListener* const listenerToRemove)
|
||||
{
|
||||
listeners.removeValue (listenerToRemove);
|
||||
}
|
||||
|
|
@ -1349,7 +1338,7 @@ void TextEditor::repaintText (int textStartIndex, int textEndIndex)
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
void TextEditor::moveCaret (int newCaretPos) throw()
|
||||
void TextEditor::moveCaret (int newCaretPos)
|
||||
{
|
||||
if (newCaretPos < 0)
|
||||
newCaretPos = 0;
|
||||
|
|
@ -1367,18 +1356,18 @@ void TextEditor::moveCaret (int newCaretPos) throw()
|
|||
}
|
||||
}
|
||||
|
||||
void TextEditor::setCaretPosition (const int newIndex) throw()
|
||||
void TextEditor::setCaretPosition (const int newIndex)
|
||||
{
|
||||
moveCursorTo (newIndex, false);
|
||||
}
|
||||
|
||||
int TextEditor::getCaretPosition() const throw()
|
||||
int TextEditor::getCaretPosition() const
|
||||
{
|
||||
return caretPosition;
|
||||
}
|
||||
|
||||
void TextEditor::scrollEditorToPositionCaret (const int desiredCaretX,
|
||||
const int desiredCaretY) throw()
|
||||
const int desiredCaretY)
|
||||
|
||||
{
|
||||
updateCaretPosition();
|
||||
|
|
@ -1420,7 +1409,7 @@ void TextEditor::scrollEditorToPositionCaret (const int desiredCaretX,
|
|||
viewport->setViewPosition (vx, vy);
|
||||
}
|
||||
|
||||
const Rectangle TextEditor::getCaretRectangle() throw()
|
||||
const Rectangle TextEditor::getCaretRectangle()
|
||||
{
|
||||
updateCaretPosition();
|
||||
|
||||
|
|
@ -1430,13 +1419,13 @@ const Rectangle TextEditor::getCaretRectangle() throw()
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
float TextEditor::getWordWrapWidth() const throw()
|
||||
float TextEditor::getWordWrapWidth() const
|
||||
{
|
||||
return (wordWrap) ? (float) (viewport->getMaximumVisibleWidth() - leftIndent - leftIndent / 2)
|
||||
: 1.0e10f;
|
||||
}
|
||||
|
||||
void TextEditor::updateTextHolderSize() throw()
|
||||
void TextEditor::updateTextHolderSize()
|
||||
{
|
||||
const float wordWrapWidth = getWordWrapWidth();
|
||||
|
||||
|
|
@ -1457,46 +1446,46 @@ void TextEditor::updateTextHolderSize() throw()
|
|||
}
|
||||
}
|
||||
|
||||
int TextEditor::getTextWidth() const throw()
|
||||
int TextEditor::getTextWidth() const
|
||||
{
|
||||
return textHolder->getWidth();
|
||||
}
|
||||
|
||||
int TextEditor::getTextHeight() const throw()
|
||||
int TextEditor::getTextHeight() const
|
||||
{
|
||||
return textHolder->getHeight();
|
||||
}
|
||||
|
||||
void TextEditor::setIndents (const int newLeftIndent,
|
||||
const int newTopIndent) throw()
|
||||
const int newTopIndent)
|
||||
{
|
||||
leftIndent = newLeftIndent;
|
||||
topIndent = newTopIndent;
|
||||
}
|
||||
|
||||
void TextEditor::setBorder (const BorderSize& border) throw()
|
||||
void TextEditor::setBorder (const BorderSize& border)
|
||||
{
|
||||
borderSize = border;
|
||||
resized();
|
||||
}
|
||||
|
||||
const BorderSize TextEditor::getBorder() const throw()
|
||||
const BorderSize TextEditor::getBorder() const
|
||||
{
|
||||
return borderSize;
|
||||
}
|
||||
|
||||
void TextEditor::setScrollToShowCursor (const bool shouldScrollToShowCursor) throw()
|
||||
void TextEditor::setScrollToShowCursor (const bool shouldScrollToShowCursor)
|
||||
{
|
||||
keepCursorOnScreen = shouldScrollToShowCursor;
|
||||
}
|
||||
|
||||
void TextEditor::updateCaretPosition() throw()
|
||||
void TextEditor::updateCaretPosition()
|
||||
{
|
||||
cursorHeight = currentFont.getHeight(); // (in case the text is empty and the call below doesn't set this value)
|
||||
getCharPosition (caretPosition, cursorX, cursorY, cursorHeight);
|
||||
}
|
||||
|
||||
void TextEditor::scrollToMakeSureCursorIsVisible() throw()
|
||||
void TextEditor::scrollToMakeSureCursorIsVisible()
|
||||
{
|
||||
updateCaretPosition();
|
||||
|
||||
|
|
@ -1542,7 +1531,7 @@ void TextEditor::scrollToMakeSureCursorIsVisible() throw()
|
|||
}
|
||||
|
||||
void TextEditor::moveCursorTo (const int newPosition,
|
||||
const bool isSelecting) throw()
|
||||
const bool isSelecting)
|
||||
{
|
||||
if (isSelecting)
|
||||
{
|
||||
|
|
@ -1600,7 +1589,7 @@ void TextEditor::moveCursorTo (const int newPosition,
|
|||
}
|
||||
|
||||
int TextEditor::getTextIndexAt (const int x,
|
||||
const int y) throw()
|
||||
const int y)
|
||||
{
|
||||
return indexAtPosition ((float) (x + viewport->getViewPositionX() - leftIndent),
|
||||
(float) (y + viewport->getViewPositionY() - topIndent));
|
||||
|
|
@ -1637,7 +1626,7 @@ void TextEditor::insertTextAtCursor (String newText)
|
|||
textChanged();
|
||||
}
|
||||
|
||||
void TextEditor::setHighlightedRegion (int startPos, int numChars) throw()
|
||||
void TextEditor::setHighlightedRegion (int startPos, int numChars)
|
||||
{
|
||||
moveCursorTo (startPos, false);
|
||||
moveCursorTo (startPos + numChars, true);
|
||||
|
|
@ -2237,7 +2226,7 @@ void TextEditor::enablementChanged()
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
void TextEditor::clearInternal (UndoManager* const um) throw()
|
||||
void TextEditor::clearInternal (UndoManager* const um)
|
||||
{
|
||||
remove (0, getTotalNumChars(), um, caretPosition);
|
||||
}
|
||||
|
|
@ -2247,7 +2236,7 @@ void TextEditor::insert (const String& text,
|
|||
const Font& font,
|
||||
const Colour& colour,
|
||||
UndoManager* const um,
|
||||
const int caretPositionToMoveTo) throw()
|
||||
const int caretPositionToMoveTo)
|
||||
{
|
||||
if (text.isNotEmpty())
|
||||
{
|
||||
|
|
@ -2299,6 +2288,7 @@ void TextEditor::insert (const String& text,
|
|||
|
||||
coalesceSimilarSections();
|
||||
totalNumChars = -1;
|
||||
valueTextNeedsUpdating = true;
|
||||
|
||||
moveCursorTo (caretPositionToMoveTo, false);
|
||||
|
||||
|
|
@ -2308,7 +2298,7 @@ void TextEditor::insert (const String& text,
|
|||
}
|
||||
|
||||
void TextEditor::reinsert (const int insertIndex,
|
||||
const VoidArray& sectionsToInsert) throw()
|
||||
const VoidArray& sectionsToInsert)
|
||||
{
|
||||
int index = 0;
|
||||
int nextIndex = 0;
|
||||
|
|
@ -2345,12 +2335,13 @@ void TextEditor::reinsert (const int insertIndex,
|
|||
|
||||
coalesceSimilarSections();
|
||||
totalNumChars = -1;
|
||||
valueTextNeedsUpdating = true;
|
||||
}
|
||||
|
||||
void TextEditor::remove (const int startIndex,
|
||||
int endIndex,
|
||||
UndoManager* const um,
|
||||
const int caretPositionToMoveTo) throw()
|
||||
const int caretPositionToMoveTo)
|
||||
{
|
||||
if (endIndex > startIndex)
|
||||
{
|
||||
|
|
@ -2434,6 +2425,7 @@ void TextEditor::remove (const int startIndex,
|
|||
|
||||
coalesceSimilarSections();
|
||||
totalNumChars = -1;
|
||||
valueTextNeedsUpdating = true;
|
||||
|
||||
moveCursorTo (caretPositionToMoveTo, false);
|
||||
|
||||
|
|
@ -2443,48 +2435,56 @@ void TextEditor::remove (const int startIndex,
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
const String TextEditor::getText() const throw()
|
||||
const String TextEditor::getText() const
|
||||
{
|
||||
String t;
|
||||
t.preallocateStorage (getTotalNumChars());
|
||||
String::Concatenator concatenator (t);
|
||||
|
||||
for (int i = 0; i < sections.size(); ++i)
|
||||
t += ((const UniformTextSection*) sections.getUnchecked(i))->getAllText();
|
||||
((const UniformTextSection*) sections.getUnchecked(i))->appendAllText (concatenator);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
const String TextEditor::getTextSubstring (const int startCharacter, const int endCharacter) const throw()
|
||||
const String TextEditor::getTextSubstring (const int startCharacter, const int endCharacter) const
|
||||
{
|
||||
String t;
|
||||
int index = 0;
|
||||
|
||||
for (int i = 0; i < sections.size(); ++i)
|
||||
if (endCharacter > startCharacter)
|
||||
{
|
||||
const UniformTextSection* const s = (const UniformTextSection*) sections.getUnchecked(i);
|
||||
const int nextIndex = index + s->getTotalLength();
|
||||
t.preallocateStorage (jmin (getTotalNumChars(), endCharacter - startCharacter));
|
||||
String::Concatenator concatenator (t);
|
||||
int index = 0;
|
||||
|
||||
if (startCharacter < nextIndex)
|
||||
for (int i = 0; i < sections.size(); ++i)
|
||||
{
|
||||
if (endCharacter <= index)
|
||||
break;
|
||||
const UniformTextSection* const s = (const UniformTextSection*) sections.getUnchecked(i);
|
||||
const int nextIndex = index + s->getTotalLength();
|
||||
|
||||
const int start = jmax (index, startCharacter);
|
||||
t += s->getTextSubstring (start - index, endCharacter - index);
|
||||
if (startCharacter < nextIndex)
|
||||
{
|
||||
if (endCharacter <= index)
|
||||
break;
|
||||
|
||||
s->appendSubstring (concatenator,
|
||||
startCharacter - index,
|
||||
endCharacter - index);
|
||||
}
|
||||
|
||||
index = nextIndex;
|
||||
}
|
||||
|
||||
index = nextIndex;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
const String TextEditor::getHighlightedText() const throw()
|
||||
const String TextEditor::getHighlightedText() const
|
||||
{
|
||||
return getTextSubstring (getHighlightedRegionStart(),
|
||||
getHighlightedRegionStart() + getHighlightedRegionLength());
|
||||
return getTextSubstring (selectionStart, selectionEnd);
|
||||
}
|
||||
|
||||
int TextEditor::getTotalNumChars() throw()
|
||||
int TextEditor::getTotalNumChars() const
|
||||
{
|
||||
if (totalNumChars < 0)
|
||||
{
|
||||
|
|
@ -2497,19 +2497,12 @@ int TextEditor::getTotalNumChars() throw()
|
|||
return totalNumChars;
|
||||
}
|
||||
|
||||
bool TextEditor::isEmpty() const throw()
|
||||
bool TextEditor::isEmpty() const
|
||||
{
|
||||
if (totalNumChars != 0)
|
||||
{
|
||||
for (int i = sections.size(); --i >= 0;)
|
||||
if (((const UniformTextSection*) sections.getUnchecked(i))->getTotalLength() > 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return getTotalNumChars() == 0;
|
||||
}
|
||||
|
||||
void TextEditor::getCharPosition (const int index, float& cx, float& cy, float& lineHeight) const throw()
|
||||
void TextEditor::getCharPosition (const int index, float& cx, float& cy, float& lineHeight) const
|
||||
{
|
||||
const float wordWrapWidth = getWordWrapWidth();
|
||||
|
||||
|
|
@ -2526,7 +2519,7 @@ void TextEditor::getCharPosition (const int index, float& cx, float& cy, float&
|
|||
}
|
||||
}
|
||||
|
||||
int TextEditor::indexAtPosition (const float x, const float y) throw()
|
||||
int TextEditor::indexAtPosition (const float x, const float y)
|
||||
{
|
||||
const float wordWrapWidth = getWordWrapWidth();
|
||||
|
||||
|
|
@ -2554,13 +2547,13 @@ int TextEditor::indexAtPosition (const float x, const float y) throw()
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
static int getCharacterCategory (const tchar character) throw()
|
||||
static int getCharacterCategory (const tchar character)
|
||||
{
|
||||
return CharacterFunctions::isLetterOrDigit (character)
|
||||
? 2 : (CharacterFunctions::isWhitespace (character) ? 0 : 1);
|
||||
}
|
||||
|
||||
int TextEditor::findWordBreakAfter (const int position) const throw()
|
||||
int TextEditor::findWordBreakAfter (const int position) const
|
||||
{
|
||||
const String t (getTextSubstring (position, position + 512));
|
||||
const int totalLength = t.length();
|
||||
|
|
@ -2580,7 +2573,7 @@ int TextEditor::findWordBreakAfter (const int position) const throw()
|
|||
return position + i;
|
||||
}
|
||||
|
||||
int TextEditor::findWordBreakBefore (const int position) const throw()
|
||||
int TextEditor::findWordBreakBefore (const int position) const
|
||||
{
|
||||
if (position <= 0)
|
||||
return 0;
|
||||
|
|
@ -2608,7 +2601,7 @@ int TextEditor::findWordBreakBefore (const int position) const throw()
|
|||
|
||||
//==============================================================================
|
||||
void TextEditor::splitSection (const int sectionIndex,
|
||||
const int charToSplitAt) throw()
|
||||
const int charToSplitAt)
|
||||
{
|
||||
jassert (sections[sectionIndex] != 0);
|
||||
|
||||
|
|
@ -2617,7 +2610,7 @@ void TextEditor::splitSection (const int sectionIndex,
|
|||
->split (charToSplitAt, passwordCharacter));
|
||||
}
|
||||
|
||||
void TextEditor::coalesceSimilarSections() throw()
|
||||
void TextEditor::coalesceSimilarSections()
|
||||
{
|
||||
for (int i = 0; i < sections.size() - 1; ++i)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "../../../utilities/juce_UndoManager.h"
|
||||
#include "../layout/juce_Viewport.h"
|
||||
#include "../menus/juce_PopupMenu.h"
|
||||
#include "../../../containers/juce_Value.h"
|
||||
class TextEditor;
|
||||
class TextHolderComponent;
|
||||
|
||||
|
|
@ -108,7 +109,7 @@ public:
|
|||
|
||||
/** Returns true if the editor is in multi-line mode.
|
||||
*/
|
||||
bool isMultiLine() const throw();
|
||||
bool isMultiLine() const;
|
||||
|
||||
//==============================================================================
|
||||
/** Changes the behaviour of the return key.
|
||||
|
|
@ -124,7 +125,7 @@ public:
|
|||
|
||||
See setReturnKeyStartsNewLine() for more info.
|
||||
*/
|
||||
bool getReturnKeyStartsNewLine() const throw() { return returnKeyStartsNewLine; }
|
||||
bool getReturnKeyStartsNewLine() const { return returnKeyStartsNewLine; }
|
||||
|
||||
/** Indicates whether the tab key should be accepted and used to input a tab character,
|
||||
or whether it gets ignored.
|
||||
|
|
@ -132,12 +133,12 @@ public:
|
|||
By default the tab key is ignored, so that it can be used to switch keyboard focus
|
||||
between components.
|
||||
*/
|
||||
void setTabKeyUsedAsCharacter (const bool shouldTabKeyBeUsed) throw();
|
||||
void setTabKeyUsedAsCharacter (const bool shouldTabKeyBeUsed);
|
||||
|
||||
/** Returns true if the tab key is being used for input.
|
||||
@see setTabKeyUsedAsCharacter
|
||||
*/
|
||||
bool isTabKeyUsedAsCharacter() const throw() { return tabKeyUsed; }
|
||||
bool isTabKeyUsedAsCharacter() const { return tabKeyUsed; }
|
||||
|
||||
//==============================================================================
|
||||
/** Changes the editor to read-only mode.
|
||||
|
|
@ -153,7 +154,7 @@ public:
|
|||
|
||||
/** Returns true if the editor is in read-only mode.
|
||||
*/
|
||||
bool isReadOnly() const throw();
|
||||
bool isReadOnly() const;
|
||||
|
||||
//==============================================================================
|
||||
/** Makes the caret visible or invisible.
|
||||
|
|
@ -162,12 +163,12 @@ public:
|
|||
|
||||
@see setCaretColour, setCaretPosition
|
||||
*/
|
||||
void setCaretVisible (const bool shouldBeVisible) throw();
|
||||
void setCaretVisible (const bool shouldBeVisible);
|
||||
|
||||
/** Returns true if the caret is enabled.
|
||||
@see setCaretVisible
|
||||
*/
|
||||
bool isCaretVisible() const throw() { return caretVisible; }
|
||||
bool isCaretVisible() const { return caretVisible; }
|
||||
|
||||
//==============================================================================
|
||||
/** Enables/disables a vertical scrollbar.
|
||||
|
|
@ -178,12 +179,12 @@ public:
|
|||
|
||||
By default the scrollbar is enabled.
|
||||
*/
|
||||
void setScrollbarsShown (bool shouldBeEnabled) throw();
|
||||
void setScrollbarsShown (bool shouldBeEnabled);
|
||||
|
||||
/** Returns true if scrollbars are enabled.
|
||||
@see setScrollbarsShown
|
||||
*/
|
||||
bool areScrollbarsShown() const throw() { return scrollbarVisible; }
|
||||
bool areScrollbarsShown() const { return scrollbarVisible; }
|
||||
|
||||
|
||||
/** Changes the password character used to disguise the text.
|
||||
|
|
@ -195,12 +196,12 @@ public:
|
|||
for a black splodge (not all fonts include this, though), or 0x2022,
|
||||
which is a bullet (probably the best choice for linux).
|
||||
*/
|
||||
void setPasswordCharacter (const tchar passwordCharacter) throw();
|
||||
void setPasswordCharacter (const tchar passwordCharacter);
|
||||
|
||||
/** Returns the current password character.
|
||||
@see setPasswordCharacter
|
||||
l */
|
||||
tchar getPasswordCharacter() const throw() { return passwordCharacter; }
|
||||
tchar getPasswordCharacter() const { return passwordCharacter; }
|
||||
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -211,16 +212,16 @@ l */
|
|||
If enabled, right-clicking (or command-clicking on the Mac) will pop up a menu
|
||||
of options such as cut/copy/paste, undo/redo, etc.
|
||||
*/
|
||||
void setPopupMenuEnabled (const bool menuEnabled) throw();
|
||||
void setPopupMenuEnabled (const bool menuEnabled);
|
||||
|
||||
/** Returns true if the right-click menu is enabled.
|
||||
@see setPopupMenuEnabled
|
||||
*/
|
||||
bool isPopupMenuEnabled() const throw() { return popupMenuEnabled; }
|
||||
bool isPopupMenuEnabled() const { return popupMenuEnabled; }
|
||||
|
||||
/** Returns true if a popup-menu is currently being displayed.
|
||||
*/
|
||||
bool isPopupMenuCurrentlyActive() const throw() { return menuActive; }
|
||||
bool isPopupMenuCurrentlyActive() const { return menuActive; }
|
||||
|
||||
//==============================================================================
|
||||
/** A set of colour IDs to use to change the colour of various aspects of the editor.
|
||||
|
|
@ -267,7 +268,7 @@ l */
|
|||
|
||||
@see applyFontToAllText
|
||||
*/
|
||||
void setFont (const Font& newFont) throw();
|
||||
void setFont (const Font& newFont);
|
||||
|
||||
/** Applies a font to all the text in the editor.
|
||||
|
||||
|
|
@ -281,7 +282,7 @@ l */
|
|||
|
||||
@see setFont
|
||||
*/
|
||||
const Font getFont() const throw();
|
||||
const Font getFont() const;
|
||||
|
||||
//==============================================================================
|
||||
/** If set to true, focusing on the editor will highlight all its text.
|
||||
|
|
@ -291,7 +292,7 @@ l */
|
|||
This is useful for boxes where you expect the user to re-enter all the
|
||||
text when they focus on the component, rather than editing what's already there.
|
||||
*/
|
||||
void setSelectAllWhenFocused (const bool b) throw();
|
||||
void setSelectAllWhenFocused (const bool b);
|
||||
|
||||
/** Sets limits on the characters that can be entered.
|
||||
|
||||
|
|
@ -301,7 +302,7 @@ l */
|
|||
this string are allowed to be entered into the editor.
|
||||
*/
|
||||
void setInputRestrictions (const int maxTextLength,
|
||||
const String& allowedCharacters = String::empty) throw();
|
||||
const String& allowedCharacters = String::empty);
|
||||
|
||||
/** When the text editor is empty, it can be set to display a message.
|
||||
|
||||
|
|
@ -309,7 +310,7 @@ l */
|
|||
string is only displayed, it's not taken to actually be the contents of
|
||||
the editor.
|
||||
*/
|
||||
void setTextToShowWhenEmpty (const String& text, const Colour& colourToUse) throw();
|
||||
void setTextToShowWhenEmpty (const String& text, const Colour& colourToUse);
|
||||
|
||||
//==============================================================================
|
||||
/** Changes the size of the scrollbars that are used.
|
||||
|
|
@ -329,26 +330,26 @@ l */
|
|||
|
||||
@see removeListener
|
||||
*/
|
||||
void addListener (TextEditorListener* const newListener) throw();
|
||||
void addListener (TextEditorListener* const newListener);
|
||||
|
||||
/** Deregisters a listener.
|
||||
|
||||
@see addListener
|
||||
*/
|
||||
void removeListener (TextEditorListener* const listenerToRemove) throw();
|
||||
void removeListener (TextEditorListener* const listenerToRemove);
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the entire contents of the editor. */
|
||||
const String getText() const throw();
|
||||
const String getText() const;
|
||||
|
||||
/** Returns a section of the contents of the editor. */
|
||||
const String getTextSubstring (const int startCharacter, const int endCharacter) const throw();
|
||||
const String getTextSubstring (const int startCharacter, const int endCharacter) const;
|
||||
|
||||
/** Returns true if there are no characters in the editor.
|
||||
|
||||
This is more efficient than calling getText().isEmpty().
|
||||
*/
|
||||
bool isEmpty() const throw();
|
||||
bool isEmpty() const;
|
||||
|
||||
/** Sets the entire content of the editor.
|
||||
|
||||
|
|
@ -365,6 +366,14 @@ l */
|
|||
void setText (const String& newText,
|
||||
const bool sendTextChangeMessage = true);
|
||||
|
||||
/** Returns a Value object that can be used to get or set the text.
|
||||
|
||||
Bear in mind that this operate quite slowly if your text box contains large
|
||||
amounts of text, as it needs to dynamically build the string that's involved. It's
|
||||
best used for small text boxes.
|
||||
*/
|
||||
Value& getTextValue();
|
||||
|
||||
/** Inserts some text at the current cursor position.
|
||||
|
||||
If a section of the text is highlighted, it will be replaced by
|
||||
|
|
@ -403,13 +412,13 @@ l */
|
|||
|
||||
@see getCaretPosition
|
||||
*/
|
||||
void setCaretPosition (const int newIndex) throw();
|
||||
void setCaretPosition (const int newIndex);
|
||||
|
||||
/** Returns the current index of the caret.
|
||||
|
||||
@see setCaretPosition
|
||||
*/
|
||||
int getCaretPosition() const throw();
|
||||
int getCaretPosition() const;
|
||||
|
||||
/** Attempts to scroll the text editor so that the caret ends up at
|
||||
a specified position.
|
||||
|
|
@ -423,19 +432,19 @@ l */
|
|||
will go as far as it can in that direction.
|
||||
*/
|
||||
void scrollEditorToPositionCaret (const int desiredCaretX,
|
||||
const int desiredCaretY) throw();
|
||||
const int desiredCaretY);
|
||||
|
||||
/** Get the graphical position of the caret.
|
||||
|
||||
The rectangle returned is relative to the component's top-left corner.
|
||||
@see scrollEditorToPositionCaret
|
||||
*/
|
||||
const Rectangle getCaretRectangle() throw();
|
||||
const Rectangle getCaretRectangle();
|
||||
|
||||
/** Selects a section of the text.
|
||||
*/
|
||||
void setHighlightedRegion (int startIndex,
|
||||
int numberOfCharactersToHighlight) throw();
|
||||
int numberOfCharactersToHighlight);
|
||||
|
||||
/** Returns the first character that is selected.
|
||||
|
||||
|
|
@ -444,68 +453,68 @@ l */
|
|||
|
||||
@see setHighlightedRegion, getHighlightedRegionLength
|
||||
*/
|
||||
int getHighlightedRegionStart() const throw() { return selectionStart; }
|
||||
int getHighlightedRegionStart() const { return selectionStart; }
|
||||
|
||||
/** Returns the number of characters that are selected.
|
||||
|
||||
@see setHighlightedRegion, getHighlightedRegionStart
|
||||
*/
|
||||
int getHighlightedRegionLength() const throw() { return jmax (0, selectionEnd - selectionStart); }
|
||||
int getHighlightedRegionLength() const { return jmax (0, selectionEnd - selectionStart); }
|
||||
|
||||
/** Returns the section of text that is currently selected. */
|
||||
const String getHighlightedText() const throw();
|
||||
const String getHighlightedText() const;
|
||||
|
||||
/** Finds the index of the character at a given position.
|
||||
|
||||
The co-ordinates are relative to the component's top-left.
|
||||
*/
|
||||
int getTextIndexAt (const int x, const int y) throw();
|
||||
int getTextIndexAt (const int x, const int y);
|
||||
|
||||
/** Counts the number of characters in the text.
|
||||
|
||||
This is quicker than getting the text as a string if you just need to know
|
||||
the length.
|
||||
*/
|
||||
int getTotalNumChars() throw();
|
||||
int getTotalNumChars() const;
|
||||
|
||||
/** Returns the total width of the text, as it is currently laid-out.
|
||||
|
||||
This may be larger than the size of the TextEditor, and can change when
|
||||
the TextEditor is resized or the text changes.
|
||||
*/
|
||||
int getTextWidth() const throw();
|
||||
int getTextWidth() const;
|
||||
|
||||
/** Returns the maximum height of the text, as it is currently laid-out.
|
||||
|
||||
This may be larger than the size of the TextEditor, and can change when
|
||||
the TextEditor is resized or the text changes.
|
||||
*/
|
||||
int getTextHeight() const throw();
|
||||
int getTextHeight() const;
|
||||
|
||||
/** Changes the size of the gap at the top and left-edge of the editor.
|
||||
|
||||
By default there's a gap of 4 pixels.
|
||||
*/
|
||||
void setIndents (const int newLeftIndent, const int newTopIndent) throw();
|
||||
void setIndents (const int newLeftIndent, const int newTopIndent);
|
||||
|
||||
/** Changes the size of border left around the edge of the component.
|
||||
|
||||
@see getBorder
|
||||
*/
|
||||
void setBorder (const BorderSize& border) throw();
|
||||
void setBorder (const BorderSize& border);
|
||||
|
||||
/** Returns the size of border around the edge of the component.
|
||||
|
||||
@see setBorder
|
||||
*/
|
||||
const BorderSize getBorder() const throw();
|
||||
const BorderSize getBorder() const;
|
||||
|
||||
/** Used to disable the auto-scrolling which keeps the cursor visible.
|
||||
|
||||
If true (the default), the editor will scroll when the cursor moves offscreen. If
|
||||
set to false, it won't.
|
||||
*/
|
||||
void setScrollToShowCursor (const bool shouldScrollToShowCursor) throw();
|
||||
void setScrollToShowCursor (const bool shouldScrollToShowCursor);
|
||||
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
|
|
@ -580,20 +589,20 @@ protected:
|
|||
|
||||
//==============================================================================
|
||||
/** Scrolls the minimum distance needed to get the caret into view. */
|
||||
void scrollToMakeSureCursorIsVisible() throw();
|
||||
void scrollToMakeSureCursorIsVisible();
|
||||
|
||||
/** @internal */
|
||||
void moveCaret (int newCaretPos) throw();
|
||||
void moveCaret (int newCaretPos);
|
||||
|
||||
/** @internal */
|
||||
void moveCursorTo (const int newPosition, const bool isSelecting) throw();
|
||||
void moveCursorTo (const int newPosition, const bool isSelecting);
|
||||
|
||||
/** Used internally to dispatch a text-change message. */
|
||||
void textChanged() throw();
|
||||
void textChanged();
|
||||
|
||||
/** Begins a new transaction in the UndoManager.
|
||||
*/
|
||||
void newTransaction() throw();
|
||||
void newTransaction();
|
||||
|
||||
/** Used internally to trigger an undo or redo. */
|
||||
void doUndoRedo (const bool isRedo);
|
||||
|
|
@ -626,6 +635,7 @@ private:
|
|||
bool keepCursorOnScreen : 1;
|
||||
bool tabKeyUsed : 1;
|
||||
bool menuActive : 1;
|
||||
bool valueTextNeedsUpdating : 1;
|
||||
|
||||
UndoManager undoManager;
|
||||
float cursorX, cursorY, cursorHeight;
|
||||
|
|
@ -634,11 +644,13 @@ private:
|
|||
int leftIndent, topIndent;
|
||||
unsigned int lastTransactionTime;
|
||||
Font currentFont;
|
||||
int totalNumChars, caretPosition;
|
||||
mutable int totalNumChars;
|
||||
int caretPosition;
|
||||
VoidArray sections;
|
||||
String textToShowWhenEmpty;
|
||||
Colour colourForTextWhenEmpty;
|
||||
tchar passwordCharacter;
|
||||
Value textValue;
|
||||
|
||||
enum
|
||||
{
|
||||
|
|
@ -653,43 +665,45 @@ private:
|
|||
friend class TextEditorInsertAction;
|
||||
friend class TextEditorRemoveAction;
|
||||
|
||||
void coalesceSimilarSections() throw();
|
||||
void splitSection (const int sectionIndex, const int charToSplitAt) throw();
|
||||
void coalesceSimilarSections();
|
||||
void splitSection (const int sectionIndex, const int charToSplitAt);
|
||||
|
||||
void clearInternal (UndoManager* const um) throw();
|
||||
void clearInternal (UndoManager* const um);
|
||||
|
||||
void insert (const String& text,
|
||||
const int insertIndex,
|
||||
const Font& font,
|
||||
const Colour& colour,
|
||||
UndoManager* const um,
|
||||
const int caretPositionToMoveTo) throw();
|
||||
const int caretPositionToMoveTo);
|
||||
|
||||
void reinsert (const int insertIndex,
|
||||
const VoidArray& sections) throw();
|
||||
const VoidArray& sections);
|
||||
|
||||
void remove (const int startIndex,
|
||||
int endIndex,
|
||||
UndoManager* const um,
|
||||
const int caretPositionToMoveTo) throw();
|
||||
const int caretPositionToMoveTo);
|
||||
|
||||
void getCharPosition (const int index,
|
||||
float& x, float& y,
|
||||
float& lineHeight) const throw();
|
||||
float& lineHeight) const;
|
||||
|
||||
void updateCaretPosition() throw();
|
||||
void updateCaretPosition();
|
||||
|
||||
void textWasChangedByValue();
|
||||
|
||||
int indexAtPosition (const float x,
|
||||
const float y) throw();
|
||||
const float y);
|
||||
|
||||
int findWordBreakAfter (const int position) const throw();
|
||||
int findWordBreakBefore (const int position) const throw();
|
||||
int findWordBreakAfter (const int position) const;
|
||||
int findWordBreakBefore (const int position) const;
|
||||
|
||||
friend class TextHolderComponent;
|
||||
friend class TextEditorViewport;
|
||||
void drawContent (Graphics& g);
|
||||
void updateTextHolderSize() throw();
|
||||
float getWordWrapWidth() const throw();
|
||||
void updateTextHolderSize();
|
||||
float getWordWrapWidth() const;
|
||||
void timerCallbackInt();
|
||||
void repaintCaret();
|
||||
void repaintText (int textStartIndex, int textEndIndex);
|
||||
|
|
|
|||
|
|
@ -1076,9 +1076,12 @@ TreeViewItem* TreeViewContentComponent::findItemAt (int y, Rectangle& itemPositi
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
#define opennessDefault 0
|
||||
#define opennessClosed 1
|
||||
#define opennessOpen 2
|
||||
enum TreeViewOpenness
|
||||
{
|
||||
opennessDefault = 0,
|
||||
opennessClosed = 1,
|
||||
opennessOpen = 2
|
||||
};
|
||||
|
||||
TreeViewItem::TreeViewItem()
|
||||
: ownerView (0),
|
||||
|
|
|
|||
|
|
@ -106,9 +106,9 @@ LookAndFeel::LookAndFeel()
|
|||
jassert (Colours::white == Colour (0xffffffff));
|
||||
|
||||
// set up the standard set of colours..
|
||||
#define textButtonColour 0xffbbbbff
|
||||
#define textHighlightColour 0x401111ee
|
||||
#define standardOutlineColour 0xb2808080
|
||||
const int textButtonColour = 0xffbbbbff;
|
||||
const int textHighlightColour = 0x401111ee;
|
||||
const int standardOutlineColour = 0xb2808080;
|
||||
|
||||
static const int standardColours[] =
|
||||
{
|
||||
|
|
|
|||
|
|
@ -46,17 +46,10 @@ static const int iconWidth = 80;
|
|||
class AlertWindowTextEditor : public TextEditor
|
||||
{
|
||||
public:
|
||||
#if JUCE_LINUX
|
||||
#define PASSWORD_CHAR 0x2022
|
||||
#else
|
||||
#define PASSWORD_CHAR 0x25cf
|
||||
#endif
|
||||
static const tchar passwordChar;
|
||||
|
||||
AlertWindowTextEditor (const String& name,
|
||||
const bool isPasswordBox)
|
||||
: TextEditor (name,
|
||||
isPasswordBox ? (const tchar) PASSWORD_CHAR
|
||||
: (const tchar) 0)
|
||||
AlertWindowTextEditor (const String& name, const bool isPasswordBox)
|
||||
: TextEditor (name, isPasswordBox ? passwordChar : 0)
|
||||
{
|
||||
setSelectAllWhenFocused (true);
|
||||
}
|
||||
|
|
@ -82,6 +75,11 @@ private:
|
|||
const AlertWindowTextEditor& operator= (const AlertWindowTextEditor&);
|
||||
};
|
||||
|
||||
#if JUCE_LINUX
|
||||
const tchar AlertWindowTextEditor::passwordChar = 0x2022;
|
||||
#else
|
||||
const tchar AlertWindowTextEditor::passwordChar = 0x25cf;
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
AlertWindow::AlertWindow (const String& title,
|
||||
|
|
|
|||
|
|
@ -32,8 +32,6 @@ BEGIN_JUCE_NAMESPACE
|
|||
#include "../imaging/juce_Image.h"
|
||||
#include "../../../utilities/juce_DeletedAtShutdown.h"
|
||||
|
||||
#define SHOULD_WRAP(x, wrapwidth) (((x) - 0.0001f) >= (wrapwidth))
|
||||
|
||||
|
||||
//==============================================================================
|
||||
PositionedGlyph::PositionedGlyph()
|
||||
|
|
@ -310,7 +308,7 @@ void GlyphArrangement::addJustifiedText (const Font& font,
|
|||
{
|
||||
lastWordBreakIndex = i + 1;
|
||||
}
|
||||
else if (SHOULD_WRAP (pg->getRight(), lineMaxX))
|
||||
else if (pg->getRight() - 0.0001f >= lineMaxX)
|
||||
{
|
||||
if (lastWordBreakIndex >= 0)
|
||||
i = lastWordBreakIndex;
|
||||
|
|
|
|||
|
|
@ -33,11 +33,6 @@ BEGIN_JUCE_NAMESPACE
|
|||
|
||||
|
||||
//==============================================================================
|
||||
static inline int makeWord (const unsigned char a, const unsigned char b)
|
||||
{
|
||||
return (b << 8) | a;
|
||||
}
|
||||
|
||||
GIFLoader::GIFLoader (InputStream& in)
|
||||
: image (0),
|
||||
input (in),
|
||||
|
|
|
|||
|
|
@ -69,8 +69,8 @@ private:
|
|||
int processExtension (int type, int& transparent);
|
||||
int readLZWByte (bool initialise, int input_code_size);
|
||||
int getCode (int code_size, bool initialise);
|
||||
bool readImage (int width, int height,
|
||||
int interlace, int transparent);
|
||||
bool readImage (int width, int height, int interlace, int transparent);
|
||||
static inline int makeWord (const uint8 a, const uint8 b) { return (b << 8) | a; }
|
||||
|
||||
GIFLoader (const GIFLoader&);
|
||||
const GIFLoader& operator= (const GIFLoader&);
|
||||
|
|
|
|||
|
|
@ -270,7 +270,7 @@ Image* juce_loadJPEGImageFromStream (InputStream& in)
|
|||
|
||||
|
||||
//==============================================================================
|
||||
static const int bufferSize = 512;
|
||||
static const int jpegBufferSize = 512;
|
||||
|
||||
struct JuceJpegDest : public jpeg_destination_mgr
|
||||
{
|
||||
|
|
@ -286,7 +286,7 @@ static void jpegWriteTerminate (j_compress_ptr cinfo)
|
|||
{
|
||||
JuceJpegDest* const dest = (JuceJpegDest*) cinfo->dest;
|
||||
|
||||
const int numToWrite = bufferSize - dest->free_in_buffer;
|
||||
const int numToWrite = jpegBufferSize - dest->free_in_buffer;
|
||||
dest->output->write (dest->buffer, numToWrite);
|
||||
}
|
||||
|
||||
|
|
@ -294,10 +294,10 @@ static boolean jpegWriteFlush (j_compress_ptr cinfo)
|
|||
{
|
||||
JuceJpegDest* const dest = (JuceJpegDest*) cinfo->dest;
|
||||
|
||||
const int numToWrite = bufferSize;
|
||||
const int numToWrite = jpegBufferSize;
|
||||
|
||||
dest->next_output_byte = (JOCTET*) dest->buffer;
|
||||
dest->free_in_buffer = bufferSize;
|
||||
dest->free_in_buffer = jpegBufferSize;
|
||||
|
||||
return dest->output->write (dest->buffer, numToWrite);
|
||||
}
|
||||
|
|
@ -326,10 +326,10 @@ bool juce_writeJPEGImageToStream (const Image& image,
|
|||
jpegCompStruct.dest = &dest;
|
||||
|
||||
dest.output = &out;
|
||||
HeapBlock <char> tempBuffer (bufferSize);
|
||||
HeapBlock <char> tempBuffer (jpegBufferSize);
|
||||
dest.buffer = (char*) tempBuffer;
|
||||
dest.next_output_byte = (JOCTET*) dest.buffer;
|
||||
dest.free_in_buffer = bufferSize;
|
||||
dest.free_in_buffer = jpegBufferSize;
|
||||
dest.init_destination = jpegWriteInit;
|
||||
dest.empty_output_buffer = jpegWriteFlush;
|
||||
dest.term_destination = jpegWriteTerminate;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue