source: branches/profile/SECEDIT/SEC_root.hxx

Last change on this file was 9533, checked in by westram, 7 years ago
  • use explicit override
    • rest
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 32.5 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : SEC_root.hxx                                      //
4//   Purpose   : secondary structure representation                //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#ifndef SEC_ROOT_HXX
12#define SEC_ROOT_HXX
13
14#ifndef _GLIBCXX_IOSFWD
15#include <iosfwd>
16#endif
17
18#ifndef AW_FONT_GROUP_HXX
19#include <aw_font_group.hxx>
20#endif
21
22#ifndef SEC_ABSPOS_HXX
23#include "SEC_abspos.hxx"
24#endif
25#ifndef SEC_GC_HXX
26#include "SEC_gc.hxx"
27#endif
28#ifndef SEC_DB_HXX
29#include "SEC_db.hxx"
30#endif
31#ifndef SECEDIT_EXTERN_HXX
32#include "secedit_extern.hxx"
33#endif
34#ifndef BI_HELIX_HXX
35#include <BI_helix.hxx>
36#endif
37
38using namespace AW;
39
40#define DATA_VERSION 3
41
42// ------------------
43//      Debugging
44
45#if defined(DEBUG)
46
47#define CHECK_INTEGRITY         // check structure integrity after changes
48#define PAINT_ABSOLUTE_POSITION // paint some positions near center (range = 0..len-1)
49
50#endif // DEBUG
51
52#ifdef CHECK_INTEGRITY
53enum SEC_CHECK_TYPE {
54    CHECK_STRUCTURE = 1,
55    CHECK_SIZE      = 2,
56    CHECK_POSITIONS = 4,
57    CHECK_ALL       = CHECK_STRUCTURE|CHECK_SIZE|CHECK_POSITIONS,
58};
59#endif
60
61// -------------------
62//      SEC_region
63
64class SEC_root;
65
66class SEC_region : virtual Noncopyable {
67private:
68    // non redundant values
69    int sequence_start, sequence_end; // sequence_end is exclusive
70
71    // cached values
72    int baseCount;             // number of real bases (-1 = uninitialized)
73
74    int * abspos_array;
75#if defined(ASSERTION_USED)
76    int   abspos_array_size;
77#endif // ASSERTION_USED
78
79    void create_abspos_array(const int *static_array);
80
81    void set_base_count(int bc) {
82        sec_assert(bc>0);
83        baseCount = bc;
84    }
85
86    void count_bases(SEC_root *root); // updates abspos_array
87
88public:
89    SEC_region(int start, int end);
90    virtual ~SEC_region();
91
92    // methods
93    void save(std::ostream & out, int indent, const XString& x_string);
94    GB_ERROR read(std::istream & in, SEC_root *root, int version);
95
96    void update_base_count(SEC_root *root) { if (baseCount == -1) count_bases(root); }
97    void invalidate_base_count();
98
99    // selector-methods
100    int get_sequence_start() const { return sequence_start; }
101    int get_sequence_end() const { return sequence_end; }
102
103    int get_base_count() const { sec_assert(baseCount != -1); return baseCount; }
104
105    bool contains_seq_position(int pos) const {
106        if (sequence_end<sequence_start) {
107            return pos<sequence_end || sequence_start <= pos;
108        }
109        return sequence_start <= pos && pos < sequence_end;
110    }
111
112    void set_sequence_portion(int start, int end) {
113        sequence_start = start;
114        sequence_end = end;
115        invalidate_base_count();
116    }
117    void generate_x_string(XString& x_string);
118    void align_helix_strands(SEC_root *root, SEC_region *other_region);
119
120    int getBasePos(int basenr) const {
121        // some helix positions do not have an absolute position
122        // in that case getBasePos() returns a neighbour position
123        int pos;
124
125        if (basenr >= 0 && basenr<get_base_count()) {
126            sec_assert(basenr >= 0);
127            sec_assert(abspos_array);
128            sec_assert(basenr<abspos_array_size);
129            pos = abspos_array[basenr];
130        }
131        else { // special case for empty strands
132            sec_assert(get_base_count() == 0);
133            sec_assert(basenr <= 0); // 0 or -1
134
135            pos = (basenr == 0) ? get_sequence_start() : get_sequence_end();
136        }
137        return pos;
138    }
139
140#if defined(CHECK_INTEGRITY)
141    void check_integrity(const SEC_root *root, SEC_CHECK_TYPE what) const;
142#endif // CHECK_INTEGRITY
143};
144
145// -------------------------
146//      SEC_constrainted
147
148class SEC_constrainted {
149    double sSize;               // standard size
150    double dSize;               // constrainted size ( = drawn size)
151    double Min, Max;            // limits for dSize (0 means : do not limitate)
152
153    void refreshDrawnSize() { dSize = (sSize<Min && Min>0) ? Min : ((sSize>Max && Max>0) ? Max : sSize); }
154
155public:
156    SEC_constrainted() : sSize(0), dSize(0), Min(0), Max(0) {}
157
158    double drawnSize() const { return dSize; } // constrainted size
159    double standardSize() const { return sSize; } // // unconstrainted size
160
161    double minSize() const { return Min; } // constraints
162    double maxSize() const { return Max; }
163
164    void setDrawnSize(double size) { // calculate constraints as needed
165        if (sSize < size) {
166            Min = size;
167            if (Min>Max) Max = 0;
168            refreshDrawnSize();
169        }
170        else if (sSize > size) {
171            Max = size;
172            if (Max<Min) Min = 0;
173            refreshDrawnSize();
174        }
175
176#if defined(DEBUG) && 0
177        printf("setDrawnSize(%.2f) -> sSize=%.2f dSize=%.2f Min=%.2f Max=%.2f\n", size, sSize, dSize, Min, Max);
178#endif // DEBUG
179    }
180
181    void setStandardSize(double size) { // set standard size (calculated from base counts)
182        sSize = size;
183        refreshDrawnSize();
184    }
185
186    void setConstraints(double low, double high) {
187        Min = low;
188        Max = high;
189        refreshDrawnSize();
190    }
191};
192
193// ---------------------
194//      SEC_oriented
195
196class SEC_base;
197
198class SEC_oriented {
199    Angle rel_angle;
200
201    mutable Angle abs_angle;
202    mutable bool  abs_angle_valid;
203
204    const Angle& calc_abs_angle() const;
205    const Angle& calc_rel_angle();
206
207    virtual SEC_base *get_parent() = 0;
208public:
209    SEC_oriented() : abs_angle_valid(false) {}
210    virtual ~SEC_oriented() {}
211
212    virtual void invalidate_sub_angles() = 0;
213    void invalidate(); // invalidates cached abs_angle of this and substructure
214
215    const Angle& get_abs_angle() const { return abs_angle_valid ? abs_angle : calc_abs_angle(); }
216    const Angle& get_rel_angle() const { return rel_angle; }
217
218    void set_rel_angle(const Angle& rel) {
219        rel_angle = rel;
220        abs_angle_valid = false;
221        invalidate_sub_angles();
222    }
223    void set_abs_angle(const Angle& abs) {
224        if (abs_angle_valid) {
225            Angle diff  = abs-get_abs_angle();
226            sec_assert(rel_angle.normal().is_normalized());
227            rel_angle  += diff;
228            abs_angle   = abs;
229        }
230        else {
231            abs_angle = abs;
232            calc_rel_angle();
233        }
234        invalidate_sub_angles();
235    }
236   
237    void set_rel_angle(const double& rel) { set_rel_angle(Angle(rel)); }
238    void set_abs_angle(const double& abs) { set_abs_angle(Angle(abs)); }
239
240    void mark_angle_absolute() { abs_angle = rel_angle; abs_angle_valid = true; } // used for root-loop (rel == abs!!)
241
242    SEC_base *parent() { return get_parent(); }
243    const SEC_base *parent() const { return const_cast<SEC_oriented*>(this)->get_parent(); }
244};
245
246
247// ----------------------
248//      SEC_BASE_TYPE
249
250enum SEC_BASE_TYPE {
251    SEC_NO_TYPE  = 0,
252    SEC_LOOP     = 1,
253    SEC_HELIX    = 2,
254    SEC_ANY_TYPE = SEC_LOOP|SEC_HELIX,
255};
256
257// -----------------
258//      SEC_base
259
260class SEC_base : public SEC_constrainted, public SEC_oriented, virtual Noncopyable { // loop or helix
261    SEC_root *root;
262
263    virtual SEC_base *get_parent() OVERRIDE = 0;
264public:
265    SEC_base(SEC_root *Root) : root(Root) {}
266    virtual ~SEC_base() OVERRIDE {}
267
268    virtual SEC_BASE_TYPE getType() const        = 0;
269    virtual const Position& get_fixpoint() const = 0;
270    virtual void reset_angles()                  = 0; // resets all strand-loop angles (of substructure)
271
272    virtual void orientationChanged() = 0; // recalc coordinates
273    virtual void sizeChanged() = 0; // recalc size and coordinates
274
275    AW_CL self() const { return (AW_CL)this; }
276    SEC_root *get_root() const { return root; }
277};
278
279class SEC_base_part : virtual Noncopyable { // segment or strand
280    SEC_region region;
281
282    virtual SEC_base *get_parent()    = 0;
283    virtual SEC_base_part *get_next() = 0;
284public:
285    SEC_base_part() : region(-1, -1) {}
286    virtual ~SEC_base_part() {}
287
288    SEC_base *parent() { return get_parent(); }
289    const SEC_base *parent() const { return const_cast<SEC_base_part*>(this)->get_parent(); }
290
291    AW_CL self() const { return parent()->self(); }
292    SEC_root *get_root() const { return parent()->get_root(); }
293
294    SEC_base_part *next() { return get_next(); } // iterates through whole structure
295    const SEC_base_part *next() const { return const_cast<SEC_base_part*>(this)->get_next(); }
296
297    const SEC_region *get_region() const { return &region; }
298    SEC_region *get_region() { return &region; }
299
300    void set_sequence_portion(int start, int end) { get_region()->set_sequence_portion(start, end); }
301    size_t getNextAbspos() const;
302};
303
304
305// ------------------
306//      SEC_helix
307
308class SEC_helix_strand;
309class SEC_loop;
310
311class SEC_helix : public SEC_base { // derived from a Noncopyable
312
313    SEC_helix_strand *strand_to_root;
314    size_t base_length; // max. # of bases in any strand
315
316    SEC_base *get_parent() OVERRIDE;
317public:
318
319    SEC_helix(SEC_root *root, SEC_helix_strand *to_root, SEC_helix_strand *from_root);
320    virtual ~SEC_helix() OVERRIDE {}
321
322    void calculate_helix_size();
323    void calculate_helix_coordinates(); // assumes root-side loop has correct coordinates
324
325    void save(std::ostream & out, int indent, const XString& x_string);
326    GB_ERROR read(std::istream & in, int version, double& old_angle_in);
327
328    size_t get_base_length()            { return base_length; }
329
330    SEC_helix_strand *strandToRoot() const { return strand_to_root; } // strand pointing to root
331    SEC_helix_strand *strandToOutside() const; // strand pointing away from root
332
333    SEC_helix_strand *strandAwayFrom(const SEC_loop *loop) const; // strand pointing away from loop
334    SEC_helix_strand *strandTowards(const SEC_loop *loop) const; // strand pointing to loop
335
336    SEC_loop *otherLoop(const SEC_loop *loop) const; // returns the other loop
337    SEC_loop *rootsideLoop() const;
338    SEC_loop *outsideLoop() const;
339
340    bool hasLoop(SEC_loop *loop) const { return loop == rootsideLoop() || loop == outsideLoop(); }
341
342    void setFixpoints(const Position& rootside, const Position& outside);
343
344    void flip();
345
346    void fixAngleBugs(int version);
347
348#if defined(CHECK_INTEGRITY)
349    void check_integrity(SEC_CHECK_TYPE what) const;
350#endif // CHECK_INTEGRITY
351
352    // SEC_oriented interface:
353    void invalidate_sub_angles() OVERRIDE;
354
355    // SEC_base interface :
356    SEC_BASE_TYPE getType() const OVERRIDE { return SEC_HELIX; }
357    void reset_angles() OVERRIDE;
358    const Position& get_fixpoint() const OVERRIDE;
359
360    void orientationChanged() OVERRIDE; // recalc coordinates
361    void sizeChanged() OVERRIDE; // recalc size and coordinates
362};
363
364// -------------------------
365//      SEC_helix_strand
366
367class SEC_segment;
368
369class SEC_helix_strand : public SEC_base_part { // derived from a Noncopyable
370    friend class SEC_helix;
371
372    SEC_loop         *origin_loop;     // Pointer to loop where strand comes from
373    SEC_helix_strand *other_strand;
374    SEC_helix        *helix_info; // used by both strands
375    SEC_segment      *next_segment; // next segment in origin_loop
376
377    // redundant values
378
379    Position fixpoint;
380    Position rightAttach, leftAttach; // rightAttach was ap1, leftAttach was ap2
381
382    void set_helix_info(SEC_helix *helix_info_)            { helix_info = helix_info_; }
383    void set_other_strand(SEC_helix_strand *other_strand_) { other_strand = other_strand_; }
384
385    // SEC_base_part interface
386    SEC_base *get_parent()  OVERRIDE { return helix_info; }
387    SEC_base_part *get_next() OVERRIDE;
388
389public:
390
391    SEC_helix_strand();
392    virtual ~SEC_helix_strand() OVERRIDE;
393
394    GB_ERROR read(SEC_loop *loop_, std::istream & in, int version);
395
396    void paint(AW_device *device);
397    void unlink(bool fromOtherStrandAsWell);
398
399    void paint_strands(AW_device *device, const Vector& strand_dir, const double& strand_length);
400    void paint_constraints(AW_device *device);
401
402    const SEC_root *get_root() const { return helix_info->get_root(); }
403    SEC_root *get_root() { return helix_info->get_root(); }
404
405    const SEC_helix *get_helix() const { return helix_info; }
406    SEC_helix *get_helix() { return helix_info; }
407
408    const SEC_helix_strand *get_other_strand() const { return other_strand; }
409    SEC_helix_strand *get_other_strand() { return other_strand; }
410
411    // fix- and attach points
412
413    const Position& get_fixpoint() const { return fixpoint; }
414    bool isRootsideFixpoint() const { return helix_info->strandToOutside() == this; }
415
416    bool pointsToRoot() const { return !isRootsideFixpoint(); }
417    bool pointsToOutside() const { return isRootsideFixpoint(); }
418
419    bool is3end() const { return get_region()->get_sequence_start() > other_strand->get_region()->get_sequence_start(); }
420
421    // Attach point (left/right when looking towards the strand from its origin loop)
422    const Position& rightAttachPoint() const { return rightAttach; }
423    const Position& leftAttachPoint() const { return leftAttach; }
424
425    const Position& startAttachPoint() const { return leftAttach; }
426    const Position& endAttachPoint() const { return other_strand->rightAttach; }
427
428    int rightAttachAbspos() const {
429        const SEC_region *reg   = get_other_strand()->get_region();
430        int               count = reg->get_base_count();
431
432        return reg->getBasePos(count ? count-1 : 0);
433    }
434    int leftAttachAbspos() const { return get_region()->getBasePos(0); }
435
436    int startAttachAbspos() const { return leftAttachAbspos(); }
437    int endAttachAbspos() const { return other_strand->rightAttachAbspos(); }
438
439    void setFixpoint(const Position& p) { fixpoint = p; }
440    void setAttachPoints(const Position& left, const Position& right) { rightAttach = right; leftAttach = left; }
441
442    // iterator methods
443
444    const SEC_segment *get_next_segment() const { return next_segment; }
445    SEC_segment *get_next_segment() { return next_segment; }
446    SEC_segment * get_previous_segment(); // expensive!
447
448    const SEC_loop *get_origin_loop() const { return origin_loop; }
449    SEC_loop *get_origin_loop() { return origin_loop; }
450    SEC_loop *get_destination_loop() { return get_other_strand()->get_origin_loop(); }
451
452    SEC_loop *get_rootside_loop() { return isRootsideFixpoint() ? get_origin_loop() : get_destination_loop(); }
453
454    void set_origin_loop(SEC_loop *loop_)                       { origin_loop = loop_; }
455    void set_next_segment(SEC_segment *next_segment_)           { next_segment=next_segment_; }
456
457#if defined(CHECK_INTEGRITY)
458    void check_integrity(SEC_CHECK_TYPE what) const;
459#endif // CHECK_INTEGRITY
460};
461
462
463// --------------------
464//      SEC_segment
465
466class SEC_segment : public SEC_base_part { // derived from a Noncopyable
467private:
468    double   alpha;             // angle of segment (i.e. how much of the loop is used by this segment)
469    Position center1, center2; // segments are not circles, they are ellipsoids
470    // center1 is used for rightAttach (of previous helix)
471    // center2 is used for leftAttach (of next helix)
472
473    SEC_helix_strand *next_helix_strand; // next helix strand after segment (pointing away from segments loop)
474    SEC_loop *loop; // the loop containing 'this'
475
476    // SEC_base_part interface
477    SEC_base *get_parent() OVERRIDE;
478    SEC_base_part *get_next() OVERRIDE { return get_next_strand(); }
479
480public:
481
482    SEC_segment();
483    virtual ~SEC_segment() OVERRIDE;
484
485    void save(std::ostream & out, int indent, const XString& x_string);
486    GB_ERROR read(SEC_loop *loop_, std::istream & in, int version);
487
488    void calculate_segment_size();
489    void calculate_segment_coordinates(const Position& start, const Position& end);
490
491    void paint(AW_device *device, SEC_helix_strand *previous_strand_pointer);
492    void unlink();
493
494    void prepare_paint(SEC_helix_strand *previous_strand_pointer, double &gamma, double &eta, double &radius, int &base_count, double &angle_step);
495
496    void mergeWith(SEC_segment *other, SEC_loop *target_loop);
497    SEC_helix_strand *split(size_t start, size_t end, SEC_segment **new_segment);
498
499
500    int is_endings_segment() {
501        int seq_start = get_region()->get_sequence_start();
502        int seq_end = get_region()->get_sequence_end();
503
504        return seq_start>seq_end;
505    }
506
507    void delete_pointer_2(SEC_helix_strand *strand) {
508        SEC_segment *segment = this;
509        while (1) {
510            SEC_helix_strand *next_strand = segment->next_helix_strand;
511
512            if (!next_strand) break;
513            if (next_strand == strand) { segment->next_helix_strand = NULL; break; }
514
515            segment = next_strand->get_next_segment();
516            if (!segment || segment==this) {
517#if defined(DEBUG)
518                printf("SEC_segment %p did not contain pointer to SEC_helix_strand %p\n", this, strand);
519#endif // DEBUG
520                break;
521            }
522        }
523    }
524
525    SEC_helix_strand *get_previous_strand();
526
527    const SEC_helix_strand *get_next_strand() const { return next_helix_strand; }
528    SEC_helix_strand *get_next_strand() { return next_helix_strand; }
529
530    const SEC_loop *get_loop() const { return loop; }
531    SEC_loop *get_loop() { return loop; }
532
533    double get_alpha() { return alpha; }
534
535    void set_next_strand(SEC_helix_strand *strand) { next_helix_strand = strand; }
536    void set_loop(SEC_loop *loop_) { loop = loop_; }
537
538#if defined(CHECK_INTEGRITY)
539    void check_integrity(SEC_CHECK_TYPE what) const;
540#endif // CHECK_INTEGRITY
541};
542
543// -----------------
544//      SEC_loop
545
546class SEC_loop : public SEC_base { // derived from a Noncopyable
547    double   Circumference;     // unit is in "segment-base-distances"
548    Position center;            // center point of loop
549    SEC_helix_strand *primary_strand; // primary strand of loop
550    // loop orientation points towards that strand
551    // for non-root-loops, this strand points towards root
552
553    void compute_circumference();
554    void compute_radius();
555
556    SEC_base *get_parent() OVERRIDE { return is_root_loop() ? 0 : get_rootside_helix(); }
557
558public:
559
560    SEC_loop(SEC_root *root_);
561    virtual ~SEC_loop() OVERRIDE;
562
563    void save(std::ostream & out, int indent, const XString& x_string);
564    GB_ERROR read(SEC_helix_strand *rootside_strand, std::istream & in, int version, double loop_angle);
565
566    void calculate_loop_size();
567    void calculate_loop_coordinates();
568
569    void paint(AW_device *device);
570    void paint_constraints(AW_device *device);
571
572    const Position& get_center() const { return center; }
573    const double& get_circumference() const { return Circumference; }
574
575    bool is_root_loop() const;
576
577    SEC_helix_strand *get_rootside_strand() const { return is_root_loop() ? 0 : primary_strand; }
578    SEC_helix *get_rootside_helix() const { return is_root_loop() ? 0 : primary_strand->get_helix(); }
579    SEC_helix_strand *get_fixpoint_strand() const { return primary_strand; }
580    SEC_helix *get_fixpoint_helix() const { return primary_strand->get_helix(); }
581
582    void set_fixpoint_strand(SEC_helix_strand *strand) { primary_strand = strand; }
583
584    void toggle_root(SEC_loop *root_loop);
585
586    void set_center(const Position& p) { center = p; }
587
588    void fixAngleBugs(int version);
589
590#if defined(CHECK_INTEGRITY)
591    void check_integrity(SEC_CHECK_TYPE what) const;
592#endif // CHECK_INTEGRITY
593
594    // SEC_oriented interface:
595    void invalidate_sub_angles() OVERRIDE;
596
597    // SEC_base interface :
598    SEC_BASE_TYPE getType() const OVERRIDE { return SEC_LOOP; }
599    void reset_angles() OVERRIDE;
600
601    const Position& get_fixpoint() const OVERRIDE {
602        // Note: does not return center for root-loop.
603        SEC_helix *helix = get_fixpoint_helix();
604        return helix->strandAwayFrom(this)->get_fixpoint();
605    }
606
607    void orientationChanged() OVERRIDE;  // recalc coordinates
608    void sizeChanged() OVERRIDE; // recalc size and coordinates
609};
610
611// --------------------------
612//      SEC_displayParams
613
614enum ShowBonds {
615    SHOW_NO_BONDS     = 0,
616    SHOW_HELIX_BONDS  = 1,
617    SHOW_NHELIX_BONDS = 2,
618};
619
620enum ShowCursorPos {
621    SHOW_NO_CURPOS    = 0,
622    SHOW_ABS_CURPOS   = 1,
623    SHOW_ECOLI_CURPOS = 2,
624    SHOW_BASE_CURPOS  = 3,
625};
626
627struct SEC_displayParams {
628    bool   show_helixNrs;       // display helix number information?
629    double distance_between_strands; // distance between strands (1.0 => strand distance == normal distance of bases in loop)
630
631    ShowBonds show_bonds;       // which bonds to show
632    short     bond_thickness;   // linewidth for bonds
633
634    bool hide_bases;            // hide bases?
635
636    ShowCursorPos show_curpos;  // which position to show at cursor
637    bool          show_ecoli_pos; // show ecoli positions?
638
639    bool display_search;        // show search results
640    bool display_sai;           // visualize SAIs
641
642    bool  show_strSkeleton;     // display the skeleton?
643    short skeleton_thickness;
644
645    bool edit_rightward;        // true = 5'->3', false = 5'<-3'
646
647#if defined(DEBUG)
648    bool show_debug;            // show debug info in structure display
649#endif // DEBUG
650
651    SEC_displayParams() { memset(this, 0, sizeof(*this)); }
652
653    void reread(AW_root *aw_root, const ED4_plugin_host& host);
654};
655
656
657// -----------------
658//      SEC_root
659
660class AWT_canvas;
661class SEC_drawn_positions;
662class SEC_db_interface;
663class SEC_graphic;
664
665enum SEC_bgpaint_mode {
666    BG_PAINT_NONE   = 0,
667    BG_PAINT_FIRST  = 1,
668    BG_PAINT_SECOND = 2,
669    BG_PAINT_BOTH   = BG_PAINT_FIRST | BG_PAINT_SECOND,
670};
671
672class SEC_root : virtual Noncopyable {
673    SEC_loop *root_loop;
674    int       cursorAbsPos;     // cursor position (-1 == unset)
675    XString  *xString;
676
677    bool constructing; // whether structure is under construction or a complete ring-structure
678
679    SEC_displayParams  displayParams;
680    SEC_db_interface  *db;
681
682    // -----------------------------
683    //      updated before paint
684
685    AW_font_group font_group;
686
687    double charRadius[SEC_GC_DATA_COUNT];  // radius and..
688    short  bg_linewidth[SEC_GC_DATA_COUNT]; // ..linewidth for drawing background (index = gc)
689    Vector center_char[SEC_GC_FONT_COUNT]; // correction vector to center the base character at its position (world coordinates)
690
691    char *bg_color;       // only valid after paint (contains EDIT4 GCs), may be NULL
692
693    Vector   *autoscroll;       // if non-zero, scroll canvas before next paint
694    int       nailedAbsPos;     // if not -1, auto-scroll such that position does not move
695    Position  drawnAbsPos;      // position where nailedAbsPos was drawn before
696
697    // --------------------------
698    //      valid after paint
699
700    SEC_drawn_positions *drawnPositions; // after paint this contains draw positions for every absolute position
701    LineVector           cursor_line; // main line of the cursor
702
703    SEC_BASE_TYPE show_constraints;
704
705
706    void paintHelixNumbers(AW_device *device);
707    void paintEcoliPositions(AW_device *device);
708#if defined(PAINT_ABSOLUTE_POSITION)
709    void showSomeAbsolutePositions(AW_device *device);
710#endif
711    void fixStructureBugs(int version);
712
713    void cacheBackgroundColor();
714
715    static bool hasBase(int pos, const char *seq, int len) {
716        sec_assert(pos<len);
717        if (pos<len) {
718            char c = seq[pos];
719            return c != '-' && c != '.';
720        }
721        return false;
722    }
723
724    void delete_root_loop() { SEC_loop *old_root_loop = root_loop; root_loop = 0; delete old_root_loop; }
725    void delete_announced_positions();
726
727public:
728
729    SEC_root();
730    ~SEC_root();
731
732    void init(SEC_graphic *gfx, AWT_canvas *scr, ED4_plugin_host& host);
733
734    bool under_construction() const { return constructing; }
735    void set_under_construction(bool construct) { constructing = construct; }
736
737    const SEC_db_interface *get_db() const { return db; }
738    const ED4_plugin_host& host() const { return db->host(); }
739    bool canDisplay() const { return db && db->canDisplay(); }
740    const BI_helix *get_helixDef() const { sec_assert(db); return db->helix(); }
741    BI_PAIR_TYPE getBondtype(int abspos) { const BI_helix *h = get_helixDef(); return h ? h->pairtype(abspos) : HELIX_NONE; }
742    const char *helixNrAt(int abspos) const { return get_helixDef()->helixNr(abspos); }
743
744    const size_t *getHelixPositions(const char *helixNr) const;
745    const double& get_char_radius(int gc) const { return charRadius[gc]; }
746
747    void reread_display_params(AW_root *aw_root, const ED4_plugin_host& Host) { displayParams.reread(aw_root, Host); }
748    const SEC_displayParams& display_params() const { return displayParams; }
749
750    bool has_xString() const { return xString; }
751    const XString& get_xString() const {
752        sec_assert(xString);
753        return *xString;
754    }
755
756#if defined(CHECK_INTEGRITY)
757    void check_integrity(SEC_CHECK_TYPE what) const;
758#endif // CHECK_INTEGRITY
759
760    // ------------------------------
761
762    void paintBackgroundColor(AW_device *device, SEC_bgpaint_mode mode, const Position& p1, int color1, int gc1, const Position& p2, int color2, int gc2, int skel_gc);
763    void paintSearchPatternStrings(AW_device *device, int clickedPos,  AW_pos xPos,  AW_pos yPos);
764
765    char *buildStructureString();
766    GB_ERROR read_data(const char *input_string, const char *x_string_in);
767
768    void add_autoscroll(const Vector& scroll);
769    void nail_position(size_t absPos); // re-position on absPos
770    void nail_cursor(); // re-position on cursor
771    void position_cursor(bool toCenter, bool evenIfVisible); // scroll/center cursor (screen-only)
772    void set_cursor(int abspos, bool performRefresh); // sets new cursor position
773
774    bool perform_autoscroll();
775
776private:
777    void calculate_size();
778    void calculate_coordinates();
779public:
780
781#if defined(CHECK_INTEGRITY)
782    void recalc() {                     check_integrity(static_cast<SEC_CHECK_TYPE>(CHECK_STRUCTURE|CHECK_SIZE));
783        calculate_coordinates();        check_integrity(CHECK_POSITIONS);
784    }
785    void relayout() {                   check_integrity(CHECK_STRUCTURE);
786        calculate_size();               check_integrity(CHECK_SIZE);
787        calculate_coordinates();        check_integrity(CHECK_POSITIONS);
788    }
789#else
790    void recalc() {
791        calculate_coordinates();
792    }
793    void relayout() {
794        calculate_size();
795        calculate_coordinates();
796    }
797#endif
798
799    GB_ERROR split_loop(int start1, int end1, int start2, int end2);
800
801    GB_ERROR paint(AW_device *device);
802    GB_ERROR unsplit_loop(SEC_helix_strand *delete_strand);
803    void     set_root(SEC_loop *loop);
804    void     create_default_bone();
805    void     generate_x_string();
806
807    void update_shown_positions();
808    bool shallDisplayPosition(int abspos) const { return db->shallDisplayPosition(abspos); }
809    void invalidate_base_positions(); // force base counts of all regions to be refreshed
810
811    int getBackgroundColor(int abspos) { return bg_color ? bg_color[abspos] : 0; }
812    const Vector& get_center_char_vector(int gc) {
813        sec_assert(gc >= SEC_GC_FIRST_FONT && gc <= SEC_GC_LAST_FONT);
814        return center_char[gc];
815    }
816
817    size_t max_index() {
818        size_t len = db->length();
819        sec_assert(len); // zero len -> no index exists
820        return len-1;
821    }
822
823    int get_cursor() const { return cursorAbsPos; }
824
825    SEC_loop *get_root_loop() const { return root_loop; }
826    void set_root_loop(SEC_loop *loop) { root_loop = loop; }
827
828    SEC_BASE_TYPE get_show_constraints() { return show_constraints; }
829    void set_show_constraints(SEC_BASE_TYPE show) { show_constraints = show; }
830
831    void set_last_drawed_cursor_position(const LineVector& line) { cursor_line = line; }
832    const LineVector& get_last_drawed_cursor_position() const { return cursor_line; }
833    void clear_last_drawed_cursor_position() { set_last_drawed_cursor_position(LineVector()); } // invalidate cursor_line
834
835    SEC_base_part *find(int pos); // find part containing position pos
836
837    void announce_base_position(int base_pos, const Position& draw_pos);
838    void clear_announced_positions();
839
840    const AW_font_group& get_font_group() const { return font_group; }
841
842
843    // draw annotation to explicit coordinates (annotation is drawn "above" line left->right)
844    void paintAnnotation(AW_device *device, int gc,
845                         const Position& annotate, const Position& left, const Position& right,
846                         double noteDistance, const char *text,
847                         bool lineToAnnotated, bool linesToLeftRight, bool boxText);
848
849    // draw a annotation next to a base (only works after paint())
850    void paintPosAnnotation(AW_device *device, int gc, size_t absPos, const char *text, bool lineToBase, bool boxText);
851};
852
853
854// --------------------------------------------------------------------------------
855// inlines:
856
857inline void SEC_helix::flip() {
858    strand_to_root = strand_to_root->get_other_strand();
859}
860
861inline SEC_helix_strand *SEC_helix::strandToOutside() const { // strand pointing away from root
862    return strandToRoot()->get_other_strand();
863}
864
865inline SEC_helix_strand *SEC_helix::strandAwayFrom(const SEC_loop *loop) const { // strand pointing away from loop
866    if (strandToRoot()->get_origin_loop() == loop) {
867        return strandToRoot();
868    }
869    sec_assert(strandToOutside()->get_origin_loop() == loop);
870    return strandToOutside();
871}
872
873inline SEC_helix_strand *SEC_helix::strandTowards(const SEC_loop *loop) const { // strand pointing to loop
874    return strandAwayFrom(loop)->get_other_strand();
875}
876
877inline SEC_loop *SEC_helix::otherLoop(const SEC_loop *loop) const { // returns loop on other side of strand
878    return strandTowards(loop)->get_origin_loop();
879}
880
881inline SEC_loop *SEC_helix::rootsideLoop() const { return strandToOutside()->get_origin_loop(); }
882inline SEC_loop *SEC_helix::outsideLoop() const { return strandToRoot()->get_origin_loop(); }
883
884inline const Position& SEC_helix::get_fixpoint() const { return strandToOutside()->get_fixpoint(); }
885
886inline void SEC_helix::setFixpoints(const Position& rootside, const Position& outside) {
887    strandToRoot()->setFixpoint(outside);
888    strandToOutside()->setFixpoint(rootside);
889}
890
891inline void SEC_helix::orientationChanged() { // recalc coordinates
892    // we need to recalculate the rootside loop, cause changing the
893    // helix-orientation affects the attached loop segments.
894
895    SEC_loop *loop = rootsideLoop();
896
897    if (loop->is_root_loop()) {
898        // at root-loop do a complete recalc
899        // (fixpoint-strand is not relayouted otherwise)
900        get_root()->recalc();
901    }
902    else {
903#if defined(CHECK_INTEGRITY)
904        loop->check_integrity(CHECK_STRUCTURE);
905        loop->check_integrity(CHECK_SIZE);
906#endif // CHECK_INTEGRITY
907        loop->calculate_loop_coordinates();
908#if defined(CHECK_INTEGRITY)
909        loop->check_integrity(CHECK_POSITIONS);
910#endif // CHECK_INTEGRITY
911    }
912}
913inline void SEC_helix::sizeChanged() { // recalc size and coordinates
914#if defined(CHECK_INTEGRITY)
915    check_integrity(CHECK_STRUCTURE);
916#endif // CHECK_INTEGRITY
917    calculate_helix_size();
918#if defined(CHECK_INTEGRITY)
919    check_integrity(CHECK_SIZE);
920#endif // CHECK_INTEGRITY
921    calculate_helix_coordinates();
922#if defined(CHECK_INTEGRITY)
923    check_integrity(CHECK_POSITIONS);
924#endif // CHECK_INTEGRITY
925}
926
927inline SEC_base *SEC_helix::get_parent() { return rootsideLoop(); }
928
929// --------------------
930
931inline SEC_base_part *SEC_helix_strand::get_next() { return get_other_strand()->get_next_segment(); }
932
933// --------------------
934
935inline bool SEC_loop::is_root_loop() const { return get_root()->get_root_loop() == this; }
936
937inline void SEC_loop::orientationChanged() { // recalc coordinates
938    if (is_root_loop()) {
939        get_root()->recalc();
940    }
941    else {
942        // loop center is calculated by helix, that is why we recalc the helix here
943
944        SEC_helix *helix = get_fixpoint_helix();
945#if defined(CHECK_INTEGRITY)
946        helix->check_integrity(CHECK_STRUCTURE);
947        helix->check_integrity(CHECK_SIZE);
948#endif // CHECK_INTEGRITY
949        helix->calculate_helix_coordinates();
950#if defined(CHECK_INTEGRITY)
951        helix->check_integrity(CHECK_POSITIONS);
952#endif // CHECK_INTEGRITY
953    }
954}
955inline void SEC_loop::sizeChanged() { // recalc size and coordinates
956    if (is_root_loop()) {
957        get_root()->relayout();
958    }
959    else {
960        SEC_helix *helix = get_fixpoint_helix();
961#if defined(CHECK_INTEGRITY)
962        helix->check_integrity(CHECK_STRUCTURE);
963#endif // CHECK_INTEGRITY
964        helix->calculate_helix_size();
965#if defined(CHECK_INTEGRITY)
966        helix->check_integrity(CHECK_SIZE);
967#endif // CHECK_INTEGRITY
968        helix->calculate_helix_coordinates();
969#if defined(CHECK_INTEGRITY)
970        helix->check_integrity(CHECK_POSITIONS);
971#endif // CHECK_INTEGRITY
972    }
973}
974
975// --------------------
976
977inline SEC_base *SEC_segment::get_parent() { return loop; }
978
979// --------------------
980
981inline bool are_adjacent_regions(const SEC_region *reg1, const SEC_region *reg2) {
982    int end1   = reg1->get_sequence_end();
983    int start2 = reg2->get_sequence_start();
984
985    if (end1 == start2) return true;
986
987    return start2 == 0;
988}
989
990
991#else
992#error SEC_root.hxx included twice
993#endif
994
Note: See TracBrowser for help on using the repository browser.