~ubuntu-branches/ubuntu/oneiric/codeblocks/oneiric

« back to all changes in this revision

Viewing changes to src/plugins/contrib/wxSmithContribItems/wxthings/wxthings/src/block.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michael Casadevall
  • Date: 2008-07-17 04:39:23 UTC
  • Revision ID: james.westby@ubuntu.com-20080717043923-gmsy5cwkdjswghkm
Tags: upstream-8.02
ImportĀ upstreamĀ versionĀ 8.02

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/////////////////////////////////////////////////////////////////////////////
 
2
// Name:        block.cpp
 
3
// Purpose:     Rectangular selection storage classes for ints and doubles
 
4
// Author:      John Labenski
 
5
// Created:     07/01/02
 
6
// Copyright:   (c) John Labenski 2004
 
7
// Licence:     wxWidgets
 
8
/////////////////////////////////////////////////////////////////////////////
 
9
 
 
10
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
 
11
    #pragma implementation "block.h"
 
12
#endif
 
13
 
 
14
// For compilers that support precompilation, includes "wx.h".
 
15
#include "wx/wxprec.h"
 
16
 
 
17
#ifdef __BORLANDC__
 
18
    #pragma hdrstop
 
19
#endif
 
20
 
 
21
#ifndef WX_PRECOMP
 
22
    //#include "wx/object.h"
 
23
#endif // WX_PRECOMP
 
24
 
 
25
#include "wx/things/block.h"
 
26
 
 
27
// use this to check to see if there is any overlap after minimizing
 
28
//#define CHECK_BLOCK_OVERLAP 1
 
29
 
 
30
#define PRINT_BLOCK(msg, b) { wxPrintf(wxT("Block '%s' %lg %lg %lg %lg\n"), msg, (double)(b).m_x1, (double)(b).m_y1, (double)(b).m_x2, (double)(b).m_y2); }
 
31
 
 
32
wxBlockInt const wxEmptyBlockInt(0, 0, -1, -1);
 
33
wxBlockDouble const wxEmptyBlockDouble(0, 0, -1, -1);
 
34
 
 
35
#include "wx/arrimpl.cpp"
 
36
WX_DEFINE_OBJARRAY(wxArrayBlockInt);
 
37
WX_DEFINE_OBJARRAY(wxArrayBlockDouble);
 
38
WX_DEFINE_OBJARRAY(wxArrayBlockIntSelection);
 
39
WX_DEFINE_OBJARRAY(wxArrayBlockDoubleSelection);
 
40
 
 
41
// ----------------------------------------------------------------------------
 
42
// Sorting functions for wxBlockInt
 
43
// ----------------------------------------------------------------------------
 
44
 
 
45
static int wxCMPFUNC_CONV wxblockint_sort_topleft_bottomright( wxBlockInt **a, wxBlockInt **b)
 
46
{
 
47
    register int y = ((*a)->m_y1 - (*b)->m_y1);
 
48
 
 
49
    if (y < 0) return -1;
 
50
    if (y == 0) return  ((*a)->m_x1 - (*b)->m_x1);
 
51
    return 1;
 
52
}
 
53
static int wxCMPFUNC_CONV wxblockint_sort_topright_bottomleft( wxBlockInt **a, wxBlockInt **b)
 
54
{
 
55
    register int y = ((*a)->m_y1 - (*b)->m_y1);
 
56
 
 
57
    if (y < 0) return -1;
 
58
    if (y == 0) return  ((*a)->m_x2 - (*b)->m_x2);
 
59
    return 1;
 
60
}
 
61
 
 
62
static int wxCMPFUNC_CONV wxblockint_sort_bottomleft_topright( wxBlockInt **a, wxBlockInt **b)
 
63
{
 
64
    register int y = ((*a)->m_y2 - (*b)->m_y2);
 
65
 
 
66
    if (y > 0) return -1;
 
67
    if (y == 0) return  ((*a)->m_x1 - (*b)->m_x1);
 
68
    return 1;
 
69
}
 
70
static int wxCMPFUNC_CONV wxblockint_sort_bottomright_topleft( wxBlockInt **a, wxBlockInt **b)
 
71
{
 
72
    register int y = ((*a)->m_y2 - (*b)->m_y2);
 
73
 
 
74
    if (y > 0) return -1;
 
75
    if (y == 0) return  ((*a)->m_x2 - (*b)->m_x2);
 
76
    return 1;
 
77
}
 
78
static int wxCMPFUNC_CONV wxblockint_sort_largest_to_smallest( wxBlockInt **a, wxBlockInt **b)
 
79
{
 
80
    return (*a)->IsLarger(**b);
 
81
}
 
82
static int wxCMPFUNC_CONV wxblockint_sort_smallest_to_largest( wxBlockInt **a, wxBlockInt **b)
 
83
{
 
84
    return -(*a)->IsLarger(**b);
 
85
}
 
86
 
 
87
void wxArrayBlockIntSort(wxArrayBlockInt &blocks, wxBlockSort_Type type)
 
88
{
 
89
    switch (type)
 
90
    {
 
91
        case wxBLOCKSORT_TOPLEFT_BOTTOMRIGHT : blocks.Sort(wxblockint_sort_topleft_bottomright); break;
 
92
        case wxBLOCKSORT_TOPRIGHT_BOTTOMLEFT : blocks.Sort(wxblockint_sort_topright_bottomleft); break;
 
93
        case wxBLOCKSORT_BOTTOMLEFT_TOPRIGHT : blocks.Sort(wxblockint_sort_bottomleft_topright); break;
 
94
        case wxBLOCKSORT_BOTTOMRIGHT_TOPLEFT : blocks.Sort(wxblockint_sort_bottomright_topleft); break;
 
95
        case wxBLOCKSORT_SMALLEST_TO_LARGEST : blocks.Sort(wxblockint_sort_smallest_to_largest); break;
 
96
        case wxBLOCKSORT_LARGEST_TO_SMALLEST : blocks.Sort(wxblockint_sort_largest_to_smallest); break;
 
97
        default : wxFAIL_MSG(wxT("unknown block sort type"));
 
98
    }
 
99
}
 
100
 
 
101
// ----------------------------------------------------------------------------
 
102
// Sorting functions for wxBlockDouble
 
103
// ----------------------------------------------------------------------------
 
104
 
 
105
static int wxCMPFUNC_CONV wxblockdouble_sort_topleft_bottomright( wxBlockDouble **a, wxBlockDouble **b)
 
106
{
 
107
    register wxDouble y = ((*a)->m_y1 - (*b)->m_y1);
 
108
 
 
109
    if (y < 0) return -1;
 
110
    if (y == 0) return  int((*a)->m_x1 - (*b)->m_x1);
 
111
    return 1;
 
112
}
 
113
static int wxCMPFUNC_CONV wxblockdouble_sort_topright_bottomleft( wxBlockDouble **a, wxBlockDouble **b)
 
114
{
 
115
    register wxDouble y = ((*a)->m_y1 - (*b)->m_y1);
 
116
 
 
117
    if (y < 0) return -1;
 
118
    if (y == 0) return  int((*a)->m_x2 - (*b)->m_x2);
 
119
    return 1;
 
120
}
 
121
 
 
122
static int wxCMPFUNC_CONV wxblockdouble_sort_bottomleft_topright( wxBlockDouble **a, wxBlockDouble **b)
 
123
{
 
124
    register wxDouble y = ((*a)->m_y2 - (*b)->m_y2);
 
125
 
 
126
    if (y > 0) return -1;
 
127
    if (y == 0) return  int((*a)->m_x1 - (*b)->m_x1);
 
128
    return 1;
 
129
}
 
130
static int wxCMPFUNC_CONV wxblockdouble_sort_bottomright_topleft( wxBlockDouble **a, wxBlockDouble **b)
 
131
{
 
132
    register wxDouble y = ((*a)->m_y2 - (*b)->m_y2);
 
133
 
 
134
    if (y > 0) return -1;
 
135
    if (y == 0) return  int((*a)->m_x2 - (*b)->m_x2);
 
136
    return 1;
 
137
}
 
138
static int wxCMPFUNC_CONV wxblockdouble_sort_largest_to_smallest( wxBlockDouble **a, wxBlockDouble **b)
 
139
{
 
140
    return (*a)->IsLarger(**b);
 
141
}
 
142
static int wxCMPFUNC_CONV wxblockdouble_sort_smallest_to_largest( wxBlockDouble **a, wxBlockDouble **b)
 
143
{
 
144
    return -(*a)->IsLarger(**b);
 
145
}
 
146
 
 
147
void wxArrayBlockDoubleSort(wxArrayBlockDouble &blocks, wxBlockSort_Type type)
 
148
{
 
149
    switch (type)
 
150
    {
 
151
        case wxBLOCKSORT_TOPLEFT_BOTTOMRIGHT : blocks.Sort(wxblockdouble_sort_topleft_bottomright); break;
 
152
        case wxBLOCKSORT_TOPRIGHT_BOTTOMLEFT : blocks.Sort(wxblockdouble_sort_topright_bottomleft); break;
 
153
        case wxBLOCKSORT_BOTTOMLEFT_TOPRIGHT : blocks.Sort(wxblockdouble_sort_bottomleft_topright); break;
 
154
        case wxBLOCKSORT_BOTTOMRIGHT_TOPLEFT : blocks.Sort(wxblockdouble_sort_bottomright_topleft); break;
 
155
        case wxBLOCKSORT_SMALLEST_TO_LARGEST : blocks.Sort(wxblockdouble_sort_smallest_to_largest); break;
 
156
        case wxBLOCKSORT_LARGEST_TO_SMALLEST : blocks.Sort(wxblockdouble_sort_largest_to_smallest); break;
 
157
        default : wxFAIL_MSG(wxT("unknown block sort type"));
 
158
    }
 
159
}
 
160
 
 
161
//=============================================================================
 
162
// wxBlockInt
 
163
//=============================================================================
 
164
 
 
165
#define TEST_BLOCKS
 
166
 
 
167
#ifdef TEST_BLOCKS
 
168
void TestBlocks()
 
169
{
 
170
    printf("Start Testing blocks -----------------------------------------\n");
 
171
    wxBlockInt b1(1,1,4,4);
 
172
    wxBlockInt b2(5,4,10,11);
 
173
    PRINT_BLOCK("b1", b1)
 
174
    PRINT_BLOCK("b2", b2)
 
175
 
 
176
    wxBlockInt iB;
 
177
    iB.Intersect(b1, b2, &iB);
 
178
    PRINT_BLOCK("Intersect b1 b2", iB)
 
179
 
 
180
    wxBlockInt uB;
 
181
    uB.Union(b1, b2, &uB);
 
182
    PRINT_BLOCK("Union b1 b2", uB)
 
183
 
 
184
    printf("Touches b1 b2 %d %d\n", b1.Touches(b2), b2.Touches(b1));
 
185
 
 
186
    b1 = wxBlockInt(2,3,7,9);
 
187
    b2 = wxBlockInt(8,3,8,3);
 
188
    printf("Touches b1 b2 %d %d\n", b1.Touches(b2), b2.Touches(b1));
 
189
 
 
190
    b1 = wxBlockInt(2,3,7,9);
 
191
    b2 = wxBlockInt(1,3,1,3);
 
192
    printf("Touches b1 b2 %d %d\n", b1.Touches(b2), b2.Touches(b1));
 
193
    iB.Intersect(b1, b2, &iB);
 
194
    PRINT_BLOCK("Intersect b1 b2", iB)
 
195
 
 
196
    b1 = wxBlockInt(2,3,7,9);
 
197
    b2 = wxBlockInt(2,2,2,2);
 
198
    printf("Touches b1 b2 %d %d\n", b1.Touches(b2), b2.Touches(b1));
 
199
 
 
200
    b1 = wxBlockInt(2,3,7,9);
 
201
    b2 = wxBlockInt(7,10,7,10);
 
202
    printf("Touches b1 b2 %d %d\n", b1.Touches(b2), b2.Touches(b1));
 
203
 
 
204
    printf("End Testing blocks -----------------------------------------\n");
 
205
    fflush(stdout);
 
206
}
 
207
#endif //TEST_BLOCKS
 
208
 
 
209
bool wxBlockInt::Touches(const wxBlockInt &b) const // see Intersects
 
210
{
 
211
    //if (((wxMax(m_x1, b.m_x1)) <= (wxMin(m_x2, b.m_x2))) &&
 
212
    //    ((wxMax(m_y1, b.m_y1)) <= (wxMin(m_y2, b.m_y2))))
 
213
    //    return true;
 
214
 
 
215
    return Intersects(wxBlockInt(b.m_x1-1, b.m_y1-1, b.m_x2+1, b.m_y2+1));
 
216
 
 
217
/*
 
218
    wxInt32 left  = wxMax( m_x1, b.m_x1 );
 
219
    wxInt32 right = wxMin( m_x2, b.m_x2 );
 
220
 
 
221
    if (labs(left - right) <= 1)
 
222
    {
 
223
        wxInt32 top    = wxMax( m_y1, b.m_y1 );
 
224
        wxInt32 bottom = wxMin( m_y2, b.m_y2 );
 
225
        if (labs(top - bottom) <= 1)
 
226
            return true;
 
227
    }
 
228
    return false;
 
229
*/
 
230
}
 
231
 
 
232
bool wxBlockInt::Combine(const wxBlockInt &b)
 
233
{
 
234
    if (!Touches(b)) return false;
 
235
    if (Contains(b)) return true;
 
236
    if (b.Contains(*this))
 
237
    {
 
238
        *this = b;
 
239
        return true;
 
240
    }
 
241
 
 
242
    wxBlockInt unionBlock;
 
243
    Union( *this, b, &unionBlock );
 
244
 
 
245
    if (unionBlock.IsEmpty()) return false;
 
246
 
 
247
    // at least one of the two blocks has to be at each corner of the union
 
248
    if (((unionBlock.GetLeftTop() == GetLeftTop()) || (unionBlock.GetLeftTop() == b.GetLeftTop())) &&
 
249
        ((unionBlock.GetRightTop() == GetRightTop()) || (unionBlock.GetRightTop() == b.GetRightTop())) &&
 
250
        ((unionBlock.GetLeftBottom() == GetLeftBottom()) || (unionBlock.GetLeftBottom() == b.GetLeftBottom())) &&
 
251
        ((unionBlock.GetRightBottom() == GetRightBottom()) || (unionBlock.GetRightBottom() == b.GetRightBottom())) )
 
252
    {
 
253
        *this = unionBlock;
 
254
        return true;
 
255
    }
 
256
 
 
257
    return false;
 
258
}
 
259
 
 
260
bool wxBlockInt::Combine( const wxBlockInt &block,
 
261
                          wxBlockInt &top, wxBlockInt &bottom,
 
262
                          wxBlockInt &left, wxBlockInt &right) const
 
263
{
 
264
    top = bottom = left = right = wxEmptyBlockInt;
 
265
 
 
266
    wxBlockInt iBlock;
 
267
    Intersect(*this, block, &iBlock);
 
268
 
 
269
    if (iBlock.IsEmpty()) return false; // nothing to combine
 
270
    if (iBlock == *this) return true;   // can combine all of this, no leftover
 
271
 
 
272
    bool combined = false;
 
273
 
 
274
    if ( block.m_y1 < m_y1 )
 
275
    {
 
276
        top = wxBlockInt( block.m_x1, block.m_y1, block.m_x2, m_y1-1 );
 
277
        combined = true;
 
278
    }
 
279
    if ( block.m_y2 > m_y2 )
 
280
    {
 
281
        bottom = wxBlockInt( block.m_x1, m_y2+1, block.m_x2, block.m_y2 );
 
282
        combined = true;
 
283
    }
 
284
    if ( block.m_x1 < m_x1 )
 
285
    {
 
286
        left = wxBlockInt( block.m_x1, iBlock.m_y1, m_x1-1, iBlock.m_y2 );
 
287
        combined = true;
 
288
    }
 
289
    if ( block.m_x2 > m_x2 )
 
290
    {
 
291
        right = wxBlockInt( m_x2+1, iBlock.m_y1, block.m_x2, iBlock.m_y2 );
 
292
        combined = true;
 
293
    }
 
294
 
 
295
    return combined;
 
296
}
 
297
 
 
298
bool wxBlockInt::Delete( const wxBlockInt &block,
 
299
                         wxBlockInt &top, wxBlockInt &bottom,
 
300
                         wxBlockInt &left, wxBlockInt &right) const
 
301
{
 
302
    top = bottom = left = right = wxEmptyBlockInt;
 
303
 
 
304
    wxBlockInt iBlock;
 
305
    Intersect(*this, block, &iBlock);
 
306
 
 
307
    if (iBlock.IsEmpty()) return false; // nothing to delete
 
308
    if (iBlock == *this) return true;   // can delete all of this, no leftover
 
309
 
 
310
    bool deleted = false;
 
311
 
 
312
    if ( m_y1 < iBlock.m_y1 )
 
313
    {
 
314
        top = wxBlockInt( m_x1, m_y1, m_x2, iBlock.m_y1-1 );
 
315
        deleted = true;
 
316
    }
 
317
    if ( GetBottom() > iBlock.GetBottom() )
 
318
    {
 
319
        bottom = wxBlockInt( m_x1, iBlock.m_y2+1, m_x2, m_y2 );
 
320
        deleted = true;
 
321
    }
 
322
    if ( m_x1 < iBlock.m_x1 )
 
323
    {
 
324
        left = wxBlockInt( m_x1, iBlock.m_y1, iBlock.m_x1-1, iBlock.m_y2 );
 
325
        deleted = true;
 
326
    }
 
327
    if ( GetRight() > iBlock.GetRight() )
 
328
    {
 
329
        right = wxBlockInt( iBlock.m_x2+1, iBlock.m_y1, m_x2, iBlock.m_y2 );
 
330
        deleted = true;
 
331
    }
 
332
 
 
333
    return deleted;
 
334
}
 
335
 
 
336
//=============================================================================
 
337
// wxBlockDouble
 
338
//=============================================================================
 
339
 
 
340
bool wxBlockDouble::Touches(const wxBlockDouble &b) const // see Intersects
 
341
{
 
342
    if (((wxMax(m_x1, b.m_x1)) <= (wxMin(m_x2, b.m_x2))) &&
 
343
        ((wxMax(m_y1, b.m_y1)) <= (wxMin(m_y2, b.m_y2))))
 
344
        return true;
 
345
 
 
346
    return false;
 
347
}
 
348
 
 
349
bool wxBlockDouble::Combine(const wxBlockDouble &b)
 
350
{
 
351
    if (!Touches(b)) return false;
 
352
    if (Contains(b)) return true;
 
353
    if (b.Contains(*this))
 
354
    {
 
355
        *this = b;
 
356
        return true;
 
357
    }
 
358
 
 
359
    wxBlockDouble unionBlock;
 
360
    Union( *this, b, &unionBlock );
 
361
 
 
362
    if (unionBlock.IsEmpty()) return false;
 
363
 
 
364
    // at least one of the two blocks has to be at each corner of the union
 
365
    if (((unionBlock.GetLeftTop() == GetLeftTop()) || (unionBlock.GetLeftTop() == b.GetLeftTop())) &&
 
366
        ((unionBlock.GetRightTop() == GetRightTop()) || (unionBlock.GetRightTop() == b.GetRightTop())) &&
 
367
        ((unionBlock.GetLeftBottom() == GetLeftBottom()) || (unionBlock.GetLeftBottom() == b.GetLeftBottom())) &&
 
368
        ((unionBlock.GetRightBottom() == GetRightBottom()) || (unionBlock.GetRightBottom() == b.GetRightBottom())) )
 
369
    {
 
370
        *this = unionBlock;
 
371
        return true;
 
372
    }
 
373
 
 
374
    return false;
 
375
}
 
376
 
 
377
bool wxBlockDouble::Combine( const wxBlockDouble &block,
 
378
                             wxBlockDouble &top, wxBlockDouble &bottom,
 
379
                             wxBlockDouble &left, wxBlockDouble &right) const
 
380
{
 
381
    top = bottom = left = right = wxEmptyBlockDouble;
 
382
 
 
383
    wxBlockDouble iBlock;
 
384
    Intersect(*this, block, &iBlock);
 
385
 
 
386
    if (iBlock.IsEmpty()) return false; // nothing to combine
 
387
    if (iBlock == *this) return true;   // can combine all of this, no leftover
 
388
 
 
389
    bool combined = false;
 
390
 
 
391
    if ( block.m_y1 < m_y1 )
 
392
    {
 
393
        top = wxBlockDouble( block.m_x1, block.m_y1, block.m_x2, m_y1 );
 
394
        combined = true;
 
395
    }
 
396
    if ( block.m_y2 > m_y2 )
 
397
    {
 
398
        bottom = wxBlockDouble( block.m_x1, m_y2, block.m_x2, block.m_y2 );
 
399
        combined = true;
 
400
    }
 
401
    if ( block.m_x1 < m_x1 )
 
402
    {
 
403
        left = wxBlockDouble( block.m_x1, iBlock.m_y1, m_x1, iBlock.m_y2 );
 
404
        combined = true;
 
405
    }
 
406
    if ( block.m_x2 > m_x2 )
 
407
    {
 
408
        right = wxBlockDouble( m_x2, iBlock.m_y1, block.m_x2, iBlock.m_y2 );
 
409
        combined = true;
 
410
    }
 
411
 
 
412
    return combined;
 
413
}
 
414
 
 
415
bool wxBlockDouble::Delete( const wxBlockDouble &block,
 
416
                            wxBlockDouble &top, wxBlockDouble &bottom,
 
417
                            wxBlockDouble &left, wxBlockDouble &right) const
 
418
{
 
419
    top = bottom = left = right = wxEmptyBlockDouble;
 
420
 
 
421
    wxBlockDouble iBlock;
 
422
    Intersect(*this, block, &iBlock);
 
423
 
 
424
    if (iBlock.IsEmpty()) return false; // nothing to delete
 
425
    if (iBlock == *this) return true;   // can delete all of this, no leftover
 
426
 
 
427
    bool deleted = false;
 
428
 
 
429
    if ( m_y1 < iBlock.m_y1 )
 
430
    {
 
431
        top = wxBlockDouble( m_x1, m_y1, m_x2, iBlock.m_y1 );
 
432
        deleted = true;
 
433
    }
 
434
    if ( m_y2 > iBlock.m_y2 )
 
435
    {
 
436
        bottom = wxBlockDouble( m_x1, iBlock.m_y2, m_x2, m_y2 );
 
437
        deleted = true;
 
438
    }
 
439
    if ( m_x1 < iBlock.m_x1 )
 
440
    {
 
441
        left = wxBlockDouble( m_x1, iBlock.m_y1, iBlock.m_x1, iBlock.m_y2 );
 
442
        deleted = true;
 
443
    }
 
444
    if ( m_x2 > iBlock.m_x2 )
 
445
    {
 
446
        right = wxBlockDouble( iBlock.m_x2, iBlock.m_y1, m_x2, iBlock.m_y2 );
 
447
        deleted = true;
 
448
    }
 
449
 
 
450
    return deleted;
 
451
}
 
452
 
 
453
//=============================================================================
 
454
// wxBlockIntSelection
 
455
//=============================================================================
 
456
wxBlockInt wxBlockIntSelection::GetBlock( int index ) const
 
457
{
 
458
    wxCHECK_MSG((index>=0) && (index<int(m_blocks.GetCount())), wxEmptyBlockInt, wxT("Invalid index"));
 
459
    return m_blocks[index];
 
460
}
 
461
 
 
462
#ifdef USE_wxRANGE
 
463
wxArrayRangeInt wxBlockIntSelection::GetBlockCol(int col) const
 
464
{
 
465
    wxArrayRangeInt ranges;
 
466
    register int n, count = m_blocks.GetCount();
 
467
    for (n=0; n<count; n++)
 
468
    {
 
469
        if ((col >= m_blocks[n].m_x1) && (col <= m_blocks[n].m_x2))
 
470
        {
 
471
            wxRangeInt range(m_blocks[n].m_y1, m_blocks[n].m_y2);
 
472
            ranges.Add(range);
 
473
        }
 
474
    }
 
475
    return ranges;
 
476
}
 
477
 
 
478
wxArrayRangeInt wxBlockIntSelection::GetBlockRow(int row) const
 
479
{
 
480
    wxArrayRangeInt ranges;
 
481
    register int n, count = m_blocks.GetCount();
 
482
    for (n=0; n<count; n++)
 
483
    {
 
484
        if ((row >= m_blocks[n].m_y1) && (row <= m_blocks[n].m_y2))
 
485
            ranges.Add(wxRangeInt(m_blocks[n].m_x1, m_blocks[n].m_x2));
 
486
    }
 
487
    return ranges;
 
488
}
 
489
#endif // USE_wxRANGE
 
490
 
 
491
wxBlockInt wxBlockIntSelection::GetBoundingBlock() const
 
492
{
 
493
    register int n, count = m_blocks.GetCount();
 
494
    if (count == 0) return wxEmptyBlockInt;
 
495
    wxBlockInt bound = m_blocks[0];
 
496
    for (n=1; n<count; n++) bound.Union(m_blocks[n]);
 
497
    return bound;
 
498
}
 
499
 
 
500
int wxBlockIntSelection::Index( int x, int y ) const
 
501
{
 
502
    register int n, count = m_blocks.GetCount();
 
503
    for (n=0; n<count; n++)
 
504
    {
 
505
        if ( m_blocks[n].Contains(x, y) )
 
506
            return n;
 
507
    }
 
508
    return wxNOT_FOUND;
 
509
}
 
510
 
 
511
int wxBlockIntSelection::Index( const wxBlockInt &b ) const
 
512
{
 
513
    register int n, count = m_blocks.GetCount();
 
514
    for (n=0; n<count; n++)
 
515
    {
 
516
        if (m_blocks[n].Intersects(b))
 
517
            return n;
 
518
    }
 
519
    return wxNOT_FOUND;
 
520
}
 
521
 
 
522
void wxBlockIntSelection::Sort(wxBlockSort_Type type)
 
523
{
 
524
    m_sort = type;
 
525
    wxArrayBlockIntSort(m_blocks, type);
 
526
}
 
527
 
 
528
bool wxBlockIntSelection::DeselectBlock( const wxBlockInt &block, bool combineNow)
 
529
{
 
530
    wxCHECK_MSG(!block.IsEmpty(), false, wxT("Invalid block") );
 
531
 
 
532
    bool done = false;
 
533
 
 
534
    wxBlockInt top, bottom, left, right;
 
535
    for (int n=0; n<int(m_blocks.GetCount()); n++)
 
536
    {
 
537
        if (m_blocks[n].Delete(block, top, bottom, left, right))
 
538
        {
 
539
            done = true;
 
540
            m_blocks.RemoveAt(n);
 
541
            n = (n > 0) ? n - 1 : -1;
 
542
 
 
543
            if (!top.IsEmpty())    m_blocks.Add(top);
 
544
            if (!bottom.IsEmpty()) m_blocks.Add(bottom);
 
545
            if (!left.IsEmpty())   m_blocks.Add(left);
 
546
            if (!right.IsEmpty())  m_blocks.Add(right);
 
547
        }
 
548
    }
 
549
 
 
550
    if (combineNow)
 
551
        Minimize();
 
552
 
 
553
    return done;
 
554
}
 
555
 
 
556
bool wxBlockIntSelection::SelectBlock( const wxBlockInt &block, bool combineNow,
 
557
                                       wxArrayBlockInt *addedBlocks )
 
558
{
 
559
    wxCHECK_MSG(!block.IsEmpty(), false, wxT("Invalid block") );
 
560
 
 
561
    //TestBlocks();
 
562
 
 
563
    wxArrayBlockInt extraBlocks;
 
564
    wxArrayBlockInt *extra = &extraBlocks;
 
565
 
 
566
    if (addedBlocks != NULL)
 
567
    {
 
568
        addedBlocks->Clear();
 
569
        extra = addedBlocks;
 
570
    }
 
571
 
 
572
    extra->Add(block);
 
573
 
 
574
    int n, count = m_blocks.GetCount();
 
575
    wxBlockInt top, bottom, left, right;
 
576
 
 
577
    for (n=0; n<count; n++)
 
578
    {
 
579
        for (int k=0; k<int(extra->GetCount()); k++)
 
580
        {
 
581
            if (m_blocks[n].Combine(extra->Item(k), top, bottom, left, right))
 
582
            {
 
583
                extra->RemoveAt(k);
 
584
                if (!top.IsEmpty())    extra->Add(top);
 
585
                if (!bottom.IsEmpty()) extra->Add(bottom);
 
586
                if (!left.IsEmpty())   extra->Add(left);
 
587
                if (!right.IsEmpty())  extra->Add(right);
 
588
                //DoMinimize( *extra );
 
589
                n = -1;
 
590
                break;
 
591
            }
 
592
        }
 
593
    }
 
594
 
 
595
    if (extra->GetCount() > 0u)
 
596
    {
 
597
        WX_APPEND_ARRAY(m_blocks, *extra);
 
598
        if (combineNow)
 
599
            Minimize();
 
600
 
 
601
        return true;
 
602
    }
 
603
 
 
604
    return false;
 
605
}
 
606
 
 
607
bool wxBlockIntSelection::Minimize()
 
608
{
 
609
    bool ret = DoMinimize(m_blocks);
 
610
    Sort(m_sort);
 
611
    return ret;
 
612
}
 
613
 
 
614
bool wxBlockIntSelection::DoMinimize(wxArrayBlockInt &blocks)
 
615
{
 
616
    int n;
 
617
    for (n=0; n<1000; n++) // should probably just take a few
 
618
    {
 
619
        if (!DoDoMinimize(blocks)) break;
 
620
    }
 
621
 
 
622
#ifdef CHECK_BLOCK_OVERLAP
 
623
    for (size_t a=0; a<blocks.GetCount(); a++)
 
624
    {
 
625
        for (size_t b=a+1; b<blocks.GetCount(); b++)
 
626
        {
 
627
            if (blocks[a].Intersects(blocks[b]))
 
628
            {
 
629
                printf("Intersecting blocks in wxBlockIntSelection::DoMinimize"); fflush(stdout);
 
630
                wxBell();
 
631
            }
 
632
        }
 
633
    }
 
634
#endif
 
635
 
 
636
    return n != 0;
 
637
}
 
638
 
 
639
bool wxBlockIntSelection::DoDoMinimize(wxArrayBlockInt &blocks)
 
640
{
 
641
//    wxBlockInt top, bottom, left, right;
 
642
    bool done = false;
 
643
    for (int i=0; i<int(blocks.GetCount())-1; i++)
 
644
    {
 
645
        for (int j=i+1; j<int(blocks.GetCount()); j++)
 
646
        {
 
647
            if (blocks[i].Combine(blocks[j]))
 
648
            {
 
649
                blocks.RemoveAt(j);
 
650
                j--;
 
651
                done = true;
 
652
                //return true;
 
653
            }
 
654
/*
 
655
            else if (blocks[i].Combine(blocks[j], top, bottom, left, right))
 
656
            {
 
657
                printf("INTERSECTION!?---------------------------\n"); fflush(stdout);
 
658
                blocks.RemoveAt(j);
 
659
                if (!top.IsEmpty())    blocks.Add(top);
 
660
                if (!bottom.IsEmpty()) blocks.Add(bottom);
 
661
                if (!left.IsEmpty())   blocks.Add(left);
 
662
                if (!right.IsEmpty())  blocks.Add(right);
 
663
                return true;
 
664
            }
 
665
*/
 
666
        }
 
667
    }
 
668
    return done;
 
669
}
 
670
 
 
671
//=============================================================================
 
672
// wxBlockDoubleSelection
 
673
//=============================================================================
 
674
wxBlockDouble wxBlockDoubleSelection::GetBlock( int index ) const
 
675
{
 
676
    wxCHECK_MSG((index>=0) && (index<int(m_blocks.GetCount())), wxEmptyBlockDouble, wxT("Invalid index"));
 
677
    return m_blocks[index];
 
678
}
 
679
 
 
680
#ifdef USE_wxRANGE
 
681
wxArrayRangeDouble wxBlockDoubleSelection::GetBlockCol(wxDouble col) const
 
682
{
 
683
    wxArrayRangeDouble ranges;
 
684
    register int n, count = m_blocks.GetCount();
 
685
    for (n=0; n<count; n++)
 
686
    {
 
687
        if ((col >= m_blocks[n].m_x1) && (col <= m_blocks[n].m_x2))
 
688
        {
 
689
            wxRangeDouble range(m_blocks[n].m_y1, m_blocks[n].m_y2);
 
690
            ranges.Add(range);
 
691
        }
 
692
    }
 
693
    return ranges;
 
694
}
 
695
 
 
696
wxArrayRangeDouble wxBlockDoubleSelection::GetBlockRow(wxDouble row) const
 
697
{
 
698
    wxArrayRangeDouble ranges;
 
699
    register int n, count = m_blocks.GetCount();
 
700
    for (n=0; n<count; n++)
 
701
    {
 
702
        if ((row >= m_blocks[n].m_y1) && (row <= m_blocks[n].m_y2))
 
703
            ranges.Add(wxRangeDouble(m_blocks[n].m_x1, m_blocks[n].m_x2));
 
704
    }
 
705
    return ranges;
 
706
}
 
707
#endif // USE_wxRANGE
 
708
 
 
709
wxBlockDouble wxBlockDoubleSelection::GetBoundingBlock() const
 
710
{
 
711
    register int n, count = m_blocks.GetCount();
 
712
    if (count == 0) return wxEmptyBlockDouble;
 
713
    wxBlockDouble bound = m_blocks[0];
 
714
    for (n=1; n<count; n++) bound.Union(m_blocks[n]);
 
715
    return bound;
 
716
}
 
717
 
 
718
int wxBlockDoubleSelection::Index( wxDouble x, wxDouble y ) const
 
719
{
 
720
    register int n, count = m_blocks.GetCount();
 
721
    for (n=0; n<count; n++)
 
722
    {
 
723
        if ( (x >= m_blocks[n].m_x1) && (y >= m_blocks[n].m_y1) &&
 
724
             (x <= m_blocks[n].m_x2) && (y <= m_blocks[n].m_y2) )
 
725
            return true;
 
726
    }
 
727
    return wxNOT_FOUND;
 
728
}
 
729
 
 
730
int wxBlockDoubleSelection::Index( const wxBlockDouble &b ) const
 
731
{
 
732
    register int n, count = m_blocks.GetCount();
 
733
    for (n=0; n<count; n++)
 
734
    {
 
735
        if (m_blocks[n].Intersects(b))
 
736
            return n;
 
737
    }
 
738
    return wxNOT_FOUND;
 
739
}
 
740
 
 
741
void wxBlockDoubleSelection::Sort(wxBlockSort_Type type)
 
742
{
 
743
    m_sort = type;
 
744
    wxArrayBlockDoubleSort(m_blocks, type);
 
745
}
 
746
 
 
747
bool wxBlockDoubleSelection::DeselectBlock( const wxBlockDouble &block, bool combineNow)
 
748
{
 
749
    //wxCHECK_MSG(!block.IsEmpty(), false, wxT("Invalid block") );
 
750
 
 
751
    bool done = false;
 
752
 
 
753
    wxBlockDouble top, bottom, left, right;
 
754
    for (int n=0; n<int(m_blocks.GetCount()); n++)
 
755
    {
 
756
        if (m_blocks[n].Delete(block, top, bottom, left, right))
 
757
        {
 
758
            done = true;
 
759
            m_blocks.RemoveAt(n);
 
760
            n = (n > 0) ? n - 1 : -1;
 
761
 
 
762
            if (!top.IsEmpty())    m_blocks.Add(top);
 
763
            if (!bottom.IsEmpty()) m_blocks.Add(bottom);
 
764
            if (!left.IsEmpty())   m_blocks.Add(left);
 
765
            if (!right.IsEmpty())  m_blocks.Add(right);
 
766
        }
 
767
    }
 
768
 
 
769
    if (combineNow)
 
770
        Minimize();
 
771
 
 
772
    return done;
 
773
}
 
774
 
 
775
bool wxBlockDoubleSelection::SelectBlock( const wxBlockDouble &block, bool combineNow)
 
776
{
 
777
    // It's valid to select a block with a width and height 0 since that means that point
 
778
    //wxCHECK_MSG(!block.IsEmpty(), false, wxT("Invalid block") );
 
779
 
 
780
    wxArrayBlockDouble extra;
 
781
    extra.Add(block);
 
782
    wxBlockDouble top, bottom, left, right;
 
783
 
 
784
    for (int n=0; n<int(m_blocks.GetCount()); n++)
 
785
    {
 
786
        for (int k=0; k<int(extra.GetCount()); k++)
 
787
        {
 
788
            bool done = false;
 
789
 
 
790
            // Doubles are different than ints - roundoff error problems
 
791
            // always use the bigger block to soak up the smaller blocks
 
792
            // this reduces problems with tiny roundoff error produced blocks
 
793
            if (m_blocks[n].Intersects(extra[k]))
 
794
            {
 
795
                if (m_blocks[n].Contains(extra[k]))
 
796
                {
 
797
                    extra.RemoveAt(k);
 
798
                    k--;
 
799
                    continue;
 
800
                }
 
801
                else if (extra[k].Contains(m_blocks[n]))
 
802
                {
 
803
                    m_blocks.RemoveAt(n);
 
804
                    n = -1;
 
805
                    break;
 
806
                }
 
807
                else if (m_blocks[n].IsLarger(extra[k]) > 0)
 
808
                {
 
809
                    done = m_blocks[n].Combine(extra[k], top, bottom, left, right);
 
810
                    if (done)
 
811
                    {
 
812
                        extra.RemoveAt(k);
 
813
                        k--;
 
814
                    }
 
815
                }
 
816
                else
 
817
                {
 
818
                    done = extra[k].Combine(m_blocks[n], top, bottom, left, right);
 
819
                    if (done)
 
820
                    {
 
821
                        m_blocks.RemoveAt(n);
 
822
                        n = -1;
 
823
                    }
 
824
                }
 
825
            }
 
826
 
 
827
            if (done)
 
828
            {
 
829
                if (!top.IsEmpty())    extra.Add(top);
 
830
                if (!bottom.IsEmpty()) extra.Add(bottom);
 
831
                if (!left.IsEmpty())   extra.Add(left);
 
832
                if (!right.IsEmpty())  extra.Add(right);
 
833
                //DoMinimize( extra );
 
834
                if (n == -1)
 
835
                    break;
 
836
            }
 
837
        }
 
838
    }
 
839
 
 
840
    if (extra.GetCount() > 0u)
 
841
    {
 
842
        WX_APPEND_ARRAY(m_blocks, extra);
 
843
        if (combineNow)
 
844
            Minimize();
 
845
 
 
846
        return true;
 
847
    }
 
848
 
 
849
    return false;
 
850
}
 
851
 
 
852
bool wxBlockDoubleSelection::Minimize()
 
853
{
 
854
    bool ret = DoMinimize(m_blocks);
 
855
    Sort(m_sort);
 
856
    return ret;
 
857
}
 
858
 
 
859
bool wxBlockDoubleSelection::DoMinimize(wxArrayBlockDouble &blocks)
 
860
{
 
861
    int n;
 
862
    for (n=0; n<1000; n++) // should probably just take < 10 at most
 
863
    {
 
864
        if (!DoDoMinimize(blocks)) break;
 
865
    }
 
866
 
 
867
#ifdef CHECK_BLOCK_OVERLAP
 
868
    for (size_t a=0; a<blocks.GetCount(); a++)
 
869
    {
 
870
        printf("Checking wxBlockDoubleSelection::DoMinimize %d =", a); PRINT_BLOCK("", blocks[a])
 
871
        for (size_t b=a+1; b<blocks.GetCount(); b++)
 
872
        {
 
873
            if (blocks[a].Intersects(blocks[b]))
 
874
            {
 
875
                printf("Intersecting blocks in wxBlockDoubleSelection::DoMinimize\n"); fflush(stdout);
 
876
                PRINT_BLOCK("",blocks[a])
 
877
                PRINT_BLOCK("",blocks[b])
 
878
                wxBell();
 
879
            }
 
880
        }
 
881
    }
 
882
#endif
 
883
 
 
884
    return n != 0;
 
885
}
 
886
 
 
887
bool wxBlockDoubleSelection::DoDoMinimize(wxArrayBlockDouble &blocks)
 
888
{
 
889
    //wxBlockDouble top, bottom, left, right;
 
890
    bool done = false;
 
891
 
 
892
    for (int i=0; i<int(blocks.GetCount())-1; i++)
 
893
    {
 
894
        for (int j=i+1; j<int(blocks.GetCount()); j++)
 
895
        {
 
896
            if (blocks[i].Combine(blocks[j]))
 
897
            {
 
898
                blocks.RemoveAt(j);
 
899
                done = true;
 
900
                j--;
 
901
            }
 
902
/*
 
903
            else if (blocks[i].Combine(blocks[j], top, bottom, left, right))
 
904
            {
 
905
                blocks.RemoveAt(j);
 
906
                if (!top.IsEmpty())    blocks.Add(top);
 
907
                if (!bottom.IsEmpty()) blocks.Add(bottom);
 
908
                if (!left.IsEmpty())   blocks.Add(left);
 
909
                if (!right.IsEmpty())  blocks.Add(right);
 
910
                return true;
 
911
            }
 
912
*/
 
913
        }
 
914
    }
 
915
    return done;
 
916
}
 
917
 
 
918
//=============================================================================
 
919
// wxBlockIntSelectionIterator - iterates through a wxBlockIntSelection
 
920
//=============================================================================
 
921
 
 
922
wxBlockIntSelectionIterator::wxBlockIntSelectionIterator( const wxBlockIntSelection &sel,
 
923
                                                          wxBISI_Type type )
 
924
{
 
925
    m_type = type;
 
926
    WX_APPEND_ARRAY(m_blocks, sel.GetBlockArray());
 
927
    m_blocks.Sort(wxblockint_sort_topleft_bottomright);
 
928
    Reset();
 
929
}
 
930
 
 
931
wxBlockIntSelectionIterator::wxBlockIntSelectionIterator( const wxArrayBlockInt &blocks,
 
932
                                                          wxBISI_Type type )
 
933
{
 
934
    m_type = type;
 
935
    WX_APPEND_ARRAY(m_blocks, blocks);
 
936
    m_blocks.Sort(wxblockint_sort_topleft_bottomright);
 
937
    Reset();
 
938
}
 
939
 
 
940
void wxBlockIntSelectionIterator::Reset()
 
941
{
 
942
    m_block_index = -1;
 
943
    m_pt = wxPoint2DInt(0, 0);
 
944
}
 
945
 
 
946
bool wxBlockIntSelectionIterator::GetNext(wxBlockInt &block)
 
947
{
 
948
    wxCHECK_MSG(m_type == wxBISI_BLOCK, false, wxT("wrong selection type"));
 
949
    if (m_block_index+1 < int(m_blocks.GetCount()))
 
950
    {
 
951
        ++m_block_index;
 
952
        block = m_blocks[m_block_index];
 
953
        return true;
 
954
    }
 
955
 
 
956
    return false;
 
957
}
 
958
 
 
959
bool wxBlockIntSelectionIterator::GetNext(wxPoint2DInt &pt)
 
960
{
 
961
    wxCHECK_MSG(m_type == wxBISI_POINT, false, wxT("wrong selection type"));
 
962
    if ((m_blocks.GetCount() < 1u) || (m_block_index >= int(m_blocks.GetCount())))
 
963
        return false;
 
964
 
 
965
    // first time here
 
966
    if (m_block_index < 0)
 
967
    {
 
968
        m_block_index = 0;
 
969
        pt = m_pt = m_blocks[m_block_index].GetLeftTop();
 
970
        return true;
 
971
    }
 
972
 
 
973
    // at end of block swap to new one
 
974
    if (m_pt == m_blocks[m_block_index].GetRightBottom())
 
975
    {
 
976
        ++m_block_index;
 
977
        if (int(m_blocks.GetCount()) > m_block_index)
 
978
        {
 
979
            pt = m_pt = m_blocks[m_block_index].GetLeftTop();
 
980
            return true;
 
981
        }
 
982
        else  // past end nothing more to check
 
983
            return  false;
 
984
    }
 
985
    // at end of col, down to next row
 
986
    if (m_pt.m_x == m_blocks[m_block_index].GetRight())
 
987
    {
 
988
        m_pt.m_x = m_blocks[m_block_index].m_x1;
 
989
        m_pt.m_y++;
 
990
 
 
991
        pt = m_pt;
 
992
        return true;
 
993
    }
 
994
 
 
995
    // increment the col
 
996
    m_pt.m_x++;
 
997
    pt = m_pt;
 
998
 
 
999
    return true;
 
1000
}
 
1001
 
 
1002
bool wxBlockIntSelectionIterator::IsInSelection(const wxPoint2DInt &pt) const
 
1003
{
 
1004
    register int n, count = m_blocks.GetCount();
 
1005
    for (n=0; n<count; n++)
 
1006
    {
 
1007
        if (m_blocks[n].Contains(pt))
 
1008
            return true;
 
1009
    }
 
1010
    return false;
 
1011
}
 
1012
 
 
1013
//=============================================================================
 
1014
// wxBlockDoubleSelectionIterator - iterates through a wxBlockDoubleSelection
 
1015
//=============================================================================
 
1016
 
 
1017
wxBlockDoubleSelectionIterator::wxBlockDoubleSelectionIterator( const wxBlockDoubleSelection &sel )
 
1018
{
 
1019
    WX_APPEND_ARRAY(m_blocks, sel.GetBlockArray());
 
1020
    m_blocks.Sort(wxblockdouble_sort_topleft_bottomright);
 
1021
    Reset();
 
1022
}
 
1023
 
 
1024
wxBlockDoubleSelectionIterator::wxBlockDoubleSelectionIterator( const wxArrayBlockDouble &blocks )
 
1025
{
 
1026
    WX_APPEND_ARRAY(m_blocks, blocks);
 
1027
    m_blocks.Sort(wxblockdouble_sort_topleft_bottomright);
 
1028
    Reset();
 
1029
}
 
1030
 
 
1031
void wxBlockDoubleSelectionIterator::Reset()
 
1032
{
 
1033
    m_block_index = 0;
 
1034
}
 
1035
 
 
1036
bool wxBlockDoubleSelectionIterator::GetNext(wxBlockDouble &block)
 
1037
{
 
1038
    if (m_block_index < m_blocks.GetCount())
 
1039
    {
 
1040
        block = m_blocks[m_block_index];
 
1041
        m_block_index++;
 
1042
        return true;
 
1043
    }
 
1044
 
 
1045
    return false;
 
1046
}
 
1047
 
 
1048
bool wxBlockDoubleSelectionIterator::IsInSelection(const wxPoint2DDouble &pt) const
 
1049
{
 
1050
    register int n, count = m_blocks.GetCount();
 
1051
    for (n=0; n<count; n++)
 
1052
    {
 
1053
        if (m_blocks[n].Contains(pt))
 
1054
            return true;
 
1055
    }
 
1056
    return false;
 
1057
}
 
1058
 
 
1059
// ============================================================================
 
1060
// ============================================================================
 
1061
// ============================================================================
 
1062
// ============================================================================
 
1063
// ============================================================================
 
1064
// Unit testing, sortof