Subversion Repositories svn.mios32

Rev

Rev 1190 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
894 tk 1
/* -*- mode:C++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- */
2
// $Id: LogBox.cpp 1724 2013-03-28 20:23:40Z tk $
3
/*
4
 * Log Box (an optimized Log window)
5
 *
6
 * ==========================================================================
7
 *
8
 *  Copyright (C) 2010 Thorsten Klose (tk@midibox.org)
9
 *  Licensed for personal non-commercial use only.
10
 *  All other rights reserved.
11
 *
12
 * ==========================================================================
13
 */
14
 
15
#include "LogBox.h"
16
 
17
 
18
//==============================================================================
19
LogBox::LogBox(const String &componentName)
20
    : ListBox(componentName, 0)
910 tk 21
    , maxRowWidth(0)
949 philetaylo 22
#if JUCE_MAJOR_VERSION==1 && JUCE_MINOR_VERSION<51
1189 tk 23
#if defined(JUCE_WIN32)
924 philetaylo 24
    , logEntryFont(Typeface::defaultTypefaceNameMono, 10.0, 0)
25
#else
949 philetaylo 26
    , logEntryFont(Typeface::defaultTypefaceNameMono, 13.0, 0)
924 philetaylo 27
#endif
949 philetaylo 28
#else 
1189 tk 29
#if defined(JUCE_WIN32)
949 philetaylo 30
    , logEntryFont(Font::getDefaultMonospacedFontName(), 10.0, 0)
31
#else
1724 tk 32
    , logEntryFont(Font::getDefaultMonospacedFontName(), 12.0, 0)
949 philetaylo 33
#endif
34
#endif
894 tk 35
{
36
    setModel(this);
37
    setMultipleSelectionEnabled(true);
38
 
924 philetaylo 39
#ifdef JUCE_WIN32
40
    setRowHeight(13);
41
#else
42
    setRowHeight(14);
43
#endif
894 tk 44
    setSize(300, 200);
45
}
46
 
47
LogBox::~LogBox()
48
{
49
}
50
 
51
//==============================================================================
52
// The following methods implement the necessary virtual functions from ListBoxModel,
53
// telling the listbox how many rows there are, painting them, etc.
54
int LogBox::getNumRows()
55
{
56
    return logEntries.size();
57
}
58
 
59
void LogBox::paintListBoxItem(int rowNumber,
60
                              Graphics& g,
61
                              int width, int height,
62
                              bool rowIsSelected)
63
{
920 tk 64
    std::pair<Colour, String> p = logEntries[rowNumber];
65
 
894 tk 66
    if( rowIsSelected )
67
        g.fillAll(Colours::lightblue);
68
 
69
    g.setFont(logEntryFont);
70
 
920 tk 71
    g.setColour(p.first);
72
    g.drawText(p.second,
894 tk 73
               5, 0, width, height,
74
               Justification::centredLeft, true);
75
}
76
 
77
//==============================================================================
78
void LogBox::paintOverChildren(Graphics& g)
79
{
80
    ListBox::paintOverChildren(g);
81
 
82
    // let it look like a text editor (I like the shadow... :-)
83
 
84
    // from getLookAndFeel().drawTextEditorOutline(g, getWidth(), getHeight(), *this);
85
 
86
    g.setColour(findColour(0x1000205)); // TextEditor::outlineColourId
87
    g.drawRect(0, 0, getWidth(), getHeight());
88
 
89
    g.setOpacity(1.0f);
90
    const Colour shadowColour(findColour(0x1000207)); // TextEditor::shadowColourId
1724 tk 91
#if 0
894 tk 92
    g.drawBevel(0, 0, getWidth(), getHeight() + 2, 3, shadowColour, shadowColour);
1724 tk 93
#else
94
    {
95
        // drawBevel has been removed in Juce 2 - copy&paste of old code:
96
        const int x = 0;
97
        const int y = 0;
98
        const int width = getWidth();
99
        const int height = getHeight() + 2;
100
        const int bevelThickness = 3;
101
        const Colour& topLeftColour = shadowColour;
102
        const Colour& bottomRightColour = shadowColour;
103
        const bool useGradient = true;
104
        const bool sharpEdgeOnOutside = true;
105
 
106
        if (g.clipRegionIntersects (Rectangle<int> (x, y, width, height))) {
107
            LowLevelGraphicsContext& context = g.getInternalContext();
108
            context.saveState();
109
 
110
            const float oldOpacity = 1.0f;//xxx state->colour.getFloatAlpha();
111
            const float ramp = oldOpacity / bevelThickness;
112
 
113
            for (int i = bevelThickness; --i >= 0;) {
114
                const float op = useGradient ? ramp * (sharpEdgeOnOutside ? bevelThickness - i : i)
115
                                                                                 : oldOpacity;
116
 
117
                context.setFill (topLeftColour.withMultipliedAlpha (op));
118
                context.fillRect (Rectangle<int> (x + i, y + i, width - i * 2, 1), false);
119
                context.setFill (topLeftColour.withMultipliedAlpha (op * 0.75f));
120
                context.fillRect (Rectangle<int> (x + i, y + i + 1, 1, height - i * 2 - 2), false);
121
                context.setFill (bottomRightColour.withMultipliedAlpha (op));
122
                context.fillRect (Rectangle<int> (x + i, y + height - i - 1, width - i * 2, 1), false);
123
                context.setFill (bottomRightColour.withMultipliedAlpha (op  * 0.75f));
124
                context.fillRect (Rectangle<int> (x + width - i - 1, y + i + 1, 1, height - i * 2 - 2), false);
125
            }
126
 
127
            context.restoreState();
128
        }
129
    }
130
#endif
894 tk 131
}
132
 
133
//==============================================================================
134
void LogBox::clear(void)
135
{
136
    logEntries.clear();
910 tk 137
    setMinimumContentWidth(maxRowWidth = 1);
894 tk 138
 
139
    updateContent();
140
    repaint(); // note: sometimes not updated without repaint()
914 philetaylo 141
    setVerticalPosition(2.0); // has to be done after updateContent()!
894 tk 142
}
143
 
920 tk 144
void LogBox::addEntry(const Colour &colour, const String &textLine)
894 tk 145
{
920 tk 146
    std::pair<Colour, String> p;
147
    p.first = colour;
148
    p.second = textLine;
149
    logEntries.add(p);
894 tk 150
 
151
    updateContent();
928 tk 152
 
937 tk 153
    int rowWidth = 30 + logEntryFont.getStringWidth(textLine);
928 tk 154
    if( rowWidth > maxRowWidth )
155
        setMinimumContentWidth(maxRowWidth = rowWidth);
156
 
914 philetaylo 157
    setVerticalPosition(2.0); // has to be done after updateContent()!
158
}
909 tk 159
 
160
 
161
//==============================================================================
162
void LogBox::copy(void)
163
{
164
    String selectedText;
165
 
166
    for(int row=0; row<getNumRows(); ++row)
167
        if( isRowSelected(row) ) {
920 tk 168
            std::pair<Colour, String> p = logEntries[row];
169
 
910 tk 170
#if JUCE_WIN32
909 tk 171
            if( selectedText != String::empty )
914 philetaylo 172
                selectedText += T("\r\n");
910 tk 173
#else
174
            if( selectedText != String::empty )
909 tk 175
                selectedText += T("\n");
910 tk 176
#endif
920 tk 177
            selectedText += p.second;
909 tk 178
        }
179
 
180
    if( selectedText != String::empty )
181
        SystemClipboard::copyTextToClipboard(selectedText);
182
}
183
 
184
void LogBox::cut(void)
185
{
186
    for(int row=0; row<getNumRows(); ++row)
187
        if( isRowSelected(row) )
188
            logEntries.remove(row);
189
 
190
    repaint(); // note: sometimes not updated without repaint()
914 philetaylo 191
    setVerticalPosition(2.0); // has to be done after updateContent()!
909 tk 192
}
193
 
194
//==============================================================================
195
void LogBox::mouseDown(const MouseEvent& e)
196
{
197
    listBoxItemClicked(-1, e);
198
}
199
 
200
void LogBox::listBoxItemClicked(int row, const MouseEvent& e)
201
{
202
    if( e.mouseWasClicked() ) {
203
        if( e.mods.isLeftButtonDown() ) {
204
            if( row == -1 )
205
                deselectAllRows();
206
        } else if( e.mods.isRightButtonDown() ) {
207
            PopupMenu m;
208
            addPopupMenuItems(m, &e);
209
 
210
            const int result = m.show();
211
 
212
            if( result != 0 )
213
                performPopupMenuAction(result);
214
        }
215
    }
216
}
217
 
218
 
219
const int baseMenuItemId = 0x7fff0000;
220
 
221
void LogBox::addPopupMenuItems(PopupMenu& m, const MouseEvent*)
222
{
223
    m.addItem(baseMenuItemId + 1, TRANS("cut"), true);
224
    m.addItem(baseMenuItemId + 2, TRANS("copy"), true);
225
    m.addSeparator();
226
    m.addItem(baseMenuItemId + 3, TRANS("select all"), true);
227
    m.addItem(baseMenuItemId + 4, TRANS("delete all"), true);
228
}
229
 
230
void LogBox::performPopupMenuAction(const int menuItemId)
231
{
232
    switch (menuItemId)
233
    {
234
    case baseMenuItemId + 1:
235
        copy();
236
        cut();
237
        break;
238
 
239
    case baseMenuItemId + 2:
240
        copy();
241
        break;
242
 
243
    case baseMenuItemId + 3:
244
        for(int row=0; row<getNumRows(); ++row)
245
            selectRow(row, false, false);
246
        break;
247
 
248
    case baseMenuItemId + 4:
249
        clear();
250
        break;
251
 
252
    default:
253
        break;
254
    }
255
}