1 |
gpertea |
45 |
/******************************************************************************** |
2 |
|
|
* * |
3 |
|
|
* * |
4 |
|
|
*********************************************************************************/ |
5 |
|
|
|
6 |
|
|
#include <stdio.h> |
7 |
|
|
#include "mdichild.h" |
8 |
|
|
#include "clv_icons.h" |
9 |
|
|
|
10 |
|
|
/*******************************************************************************/ |
11 |
|
|
|
12 |
|
|
|
13 |
|
|
// ========= static members initialization: ================ |
14 |
|
|
short MDIChild::numInst=0; //number of instances |
15 |
|
|
FXFont* MDIChild::ifont=NULL; |
16 |
|
|
FXIcon* MDIChild::icnDefCS=NULL; |
17 |
|
|
FXIcon* MDIChild::icnBaseCS=NULL; |
18 |
|
|
FXIcon* MDIChild::icnDensCS=NULL; |
19 |
|
|
//============================================================ |
20 |
|
|
|
21 |
|
|
// Map |
22 |
|
|
FXDEFMAP(MDIChild) MDIChildMap[]={ |
23 |
|
|
//________Message_Type____________________ID___________________Message_Handler________ |
24 |
|
|
FXMAPFUNCS(SEL_CHANGED, MDIChild::ID_CLXZOOM, |
25 |
|
|
MDIChild::ID_CLYZOOM, MDIChild::onCmdClZoom), |
26 |
|
|
FXMAPFUNC(SEL_COMMAND, MDIChild::ID_CLNOZOOM, MDIChild::onNoZoom), |
27 |
|
|
FXMAPFUNC(SEL_COMMAND, MDIChild::ID_CLGRPS, MDIChild::onCmdGrps), |
28 |
|
|
FXMAPFUNC(SEL_COMMAND, MDIChild::ID_CL1PXZOOM, MDIChild::onMaxZoom), |
29 |
|
|
FXMAPFUNC(SEL_CLICKED, MDIChild::ID_CLVIEW, MDIChild::onSeqSelect), |
30 |
|
|
FXMAPFUNC(SEL_RIGHTBUTTONPRESS, MDIChild::ID_CLVIEW, MDIChild::onRMouseDown), |
31 |
|
|
FXMAPFUNC(SEL_RIGHTBUTTONRELEASE, MDIChild::ID_CLVIEW, MDIChild::onRMouseUp), |
32 |
|
|
FXMAPFUNC(SEL_MIDDLEBUTTONPRESS, MDIChild::ID_CLVIEW, MDIChild::onMMouseDown), |
33 |
|
|
FXMAPFUNC(SEL_MIDDLEBUTTONRELEASE, MDIChild::ID_CLVIEW, MDIChild::onMMouseUp), |
34 |
|
|
FXMAPFUNC(SEL_MOTION, MDIChild::ID_CLVIEW, MDIChild::onMouseMove), |
35 |
|
|
FXMAPFUNCS(SEL_COMMAND, MDIChild::ID_CSTYLE1, |
36 |
|
|
MDIChild::ID_CSTYLE3, MDIChild::onColorOption), |
37 |
|
|
FXMAPFUNC(SEL_COMMAND, MDIChild::ID_CONTIG, MDIChild::onSelContig), |
38 |
|
|
FXMAPFUNC(SEL_COMMAND, MDIChild::ID_HIDEGAPS, MDIChild::onHideGaps), |
39 |
|
|
FXMAPFUNC(SEL_COMMAND, MDIChild::ID_SELSEQ, MDIChild::onSelSeq), |
40 |
|
|
FXMAPFUNC(SEL_CONFIGURE, 0, MDIChild::onMaxRestore), |
41 |
|
|
}; |
42 |
|
|
|
43 |
|
|
|
44 |
|
|
// Object implementation |
45 |
|
|
FXIMPLEMENT(MDIChild,FXMDIChild,MDIChildMap,ARRAYNUMBER(MDIChildMap)) |
46 |
|
|
|
47 |
|
|
|
48 |
|
|
/*******************************************************************************/ |
49 |
|
|
// Make some windows |
50 |
|
|
MDIChild::MDIChild(FXMDIClient* p,const FXString& name,FXIcon* ic, |
51 |
|
|
FXMenuPane* mn,FXuint opts,FXint x,FXint y,FXint w,FXint h) |
52 |
|
|
:FXMDIChild(p,name, ic, mn, opts, x, y, w, h) { |
53 |
|
|
FXString s; |
54 |
|
|
// Tooltip |
55 |
|
|
wasMaximized=false; |
56 |
|
|
new FXToolTip(getApp()); |
57 |
|
|
layoutparser=NULL; |
58 |
|
|
groupHolder=NULL; |
59 |
|
|
zooming=false; |
60 |
|
|
panning=false; |
61 |
|
|
prevColumn=-1; |
62 |
|
|
contents=new FXVerticalFrame(this,FRAME_NONE|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0,0,0,0,0); |
63 |
|
|
|
64 |
|
|
vframe=new FXVerticalFrame(contents,FRAME_NONE|LAYOUT_FILL_Y|LAYOUT_FILL_X, |
65 |
|
|
0,0,0,0,0,0,0,0); |
66 |
|
|
FXHorizontalFrame* hf=new FXHorizontalFrame(vframe,FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP); |
67 |
|
|
//contig and option buttons: |
68 |
|
|
new FXLabel(hf, "Cluster:", NULL, LAYOUT_CENTER_Y); |
69 |
|
|
|
70 |
|
|
selcontig=new FXComboBox(hf,32,this,ID_CONTIG, |
71 |
|
|
COMBOBOX_NORMAL|FRAME_SUNKEN|FRAME_THICK|LAYOUT_CENTER_Y); |
72 |
|
|
selcontig->setNumVisible(10); |
73 |
|
|
selcontig->setEditable(FALSE); |
74 |
|
|
pop=new FXPopup(this); |
75 |
|
|
if (numInst<=0) { |
76 |
|
|
icnDefCS=new FXXPMIcon(getApp(), cs_default, FXRGB(192,192,192),IMAGE_ALPHACOLOR); |
77 |
|
|
icnBaseCS=new FXXPMIcon(getApp(), cs_base, FXRGB(192,192,192),IMAGE_ALPHACOLOR); |
78 |
|
|
icnDensCS=new FXXPMIcon(getApp(), cs_density, FXRGB(192,192,192),IMAGE_ALPHACOLOR); |
79 |
|
|
ifont=new FXFont(getApp(),"helvetica", 10, FXFont::Bold); //info font |
80 |
|
|
} |
81 |
|
|
numInst++; |
82 |
|
|
|
83 |
|
|
clropt1=new FXOption(pop,"\t\tCoverage/quality color style", |
84 |
|
|
icnDensCS, |
85 |
|
|
this,ID_CSTYLE2,JUSTIFY_HZ_APART); |
86 |
|
|
clropt2=new FXOption(pop,"\t\tSimple/Group color style", icnDefCS, |
87 |
|
|
this, ID_CSTYLE1,JUSTIFY_HZ_APART); |
88 |
|
|
clropt3=new FXOption(pop,"\t\tNucleotide color style", |
89 |
|
|
icnBaseCS, |
90 |
|
|
this,ID_CSTYLE3,JUSTIFY_HZ_APART); |
91 |
|
|
new FXOptionMenu(hf, pop, |
92 |
|
|
LAYOUT_TOP|FRAME_RAISED|FRAME_THICK|JUSTIFY_HZ_APART); |
93 |
|
|
new FXButton(hf, "G\tLoad groups\tShow groups loaded from another layout file", |
94 |
|
|
NULL,this, ID_CLGRPS, |
95 |
|
|
LAYOUT_TOP|FRAME_RAISED|FRAME_THICK|JUSTIFY_HZ_APART); |
96 |
|
|
cbgaps=new FXCheckButton(hf,"hide contig gaps",this, MDIChild::ID_HIDEGAPS); |
97 |
|
|
hframe=new FXHorizontalFrame(vframe,FRAME_NONE|LAYOUT_FILL_X|LAYOUT_FILL_Y|ICON_BEFORE_TEXT, |
98 |
|
|
0,0,0,0,0,0,0,0); |
99 |
|
|
vframe= new FXVerticalFrame(hframe,FRAME_NONE|LAYOUT_FILL_Y|LAYOUT_FILL_X, |
100 |
|
|
0,0,0,0,0,0,0,0); |
101 |
|
|
clframe=new FXHorizontalFrame(vframe,FRAME_SUNKEN|LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_BOTTOM, |
102 |
|
|
0,0,0,0,0,0,0,0); |
103 |
|
|
alignview=new FXGView(clframe, this,MDIChild::ID_CLVIEW, LAYOUT_FILL_X|LAYOUT_FILL_Y); |
104 |
|
|
|
105 |
|
|
hf = new FXHorizontalFrame(vframe,FRAME_SUNKEN|LAYOUT_FILL_X, |
106 |
|
|
0,0,0,0,0,0,0,0); |
107 |
|
|
//=== seq_info box: |
108 |
|
|
FXVerticalFrame* vf = new FXVerticalFrame(hf, FRAME_NONE|LAYOUT_CENTER_Y|LAYOUT_FILL_X); |
109 |
|
|
FXHorizontalFrame* hhf=new FXHorizontalFrame(vf, |
110 |
|
|
FRAME_NONE|LAYOUT_CENTER_Y|LAYOUT_FILL_X, 0,0,0,0,0,0,0,0); |
111 |
|
|
selseq=new FXComboBox(hhf,28,this,ID_SELSEQ, |
112 |
|
|
COMBOBOX_NORMAL|FRAME_SUNKEN|FRAME_THICK|LAYOUT_CENTER_Y); |
113 |
|
|
selseq->setNumVisible(12); |
114 |
|
|
selseq->setEditable(FALSE); |
115 |
|
|
seqData = new FXLabel(hhf, " ", NULL, |
116 |
|
|
FRAME_SUNKEN|JUSTIFY_LEFT|LAYOUT_FILL_X); |
117 |
|
|
//seqComment=new FXTextField(vf,120,NULL,0,JUSTIFY_LEFT|FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_X); |
118 |
|
|
seqData->setFont(ifont); |
119 |
|
|
seqAsmInfo=new FXLabel(vf, " ", NULL, |
120 |
|
|
FRAME_SUNKEN|JUSTIFY_LEFT|LAYOUT_FILL_X); |
121 |
|
|
seqAsmInfo->setFont(ifont); |
122 |
|
|
//===slider box: |
123 |
|
|
vf = new FXVerticalFrame(hf, FRAME_RAISED); |
124 |
|
|
sliderZX=new FXSlider(vf,this,MDIChild::ID_CLXZOOM, |
125 |
|
|
LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT|FRAME_RAISED, |
126 |
|
|
0,0,160,22,0,0,0,0); |
127 |
|
|
|
128 |
|
|
hf=new FXHorizontalFrame(vf,FRAME_NONE|LAYOUT_FILL_X,0,0,0,0,0,0,0,0); |
129 |
|
|
nozoomBtn=new FXButton(hf, "&1x1",NULL, this, MDIChild::ID_CLNOZOOM, |
130 |
|
|
FRAME_RAISED|FRAME_THICK|LAYOUT_CENTER_Y); |
131 |
|
|
new FXButton(hf, "1p&x",NULL, this, MDIChild::ID_CL1PXZOOM, |
132 |
|
|
FRAME_RAISED|FRAME_THICK|LAYOUT_CENTER_X|LAYOUT_CENTER_Y); |
133 |
|
|
zxLabel=new FXLabel(hf, "1.000", NULL, |
134 |
|
|
FRAME_SUNKEN|JUSTIFY_RIGHT|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT|LAYOUT_RIGHT|LAYOUT_CENTER_Y, |
135 |
|
|
0,0,6*6,14); |
136 |
|
|
|
137 |
|
|
s.format("%02.3f",alignview->getZoomX()); |
138 |
|
|
zxLabel->setText(s); |
139 |
|
|
columnInfo=new FXLabel(vframe, " ", |
140 |
|
|
NULL, JUSTIFY_LEFT|FRAME_SUNKEN|LAYOUT_FILL_X); |
141 |
|
|
//=== vframe filled === |
142 |
|
|
|
143 |
|
|
toolframe=new FXVerticalFrame(hframe,FRAME_RAISED|LAYOUT_FILL_Y); |
144 |
|
|
//new FXLabel(toolframe, "Y Scale:", NULL, LAYOUT_CENTER_X); |
145 |
|
|
sliderZY=new FXSlider(toolframe,this,MDIChild::ID_CLYZOOM, |
146 |
|
|
SLIDER_VERTICAL|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT|LAYOUT_CENTER_X|FRAME_RAISED, |
147 |
|
|
0,0,22,140,0,0,0,0); |
148 |
|
|
|
149 |
|
|
sliderZY->setRange(10,100); // |
150 |
|
|
sliderZY->setValue((FXint)(alignview->getZoomY()*100)); |
151 |
|
|
|
152 |
|
|
sliderZX->setRange(10,1000);// |
153 |
|
|
sliderZX->setValue((FXint)(alignview->getZoomX()*1000)); |
154 |
|
|
s.format("%02.2f",alignview->getZoomY()); |
155 |
|
|
zyLabel=new FXLabel(toolframe, s, NULL, |
156 |
|
|
FRAME_SUNKEN|LAYOUT_CENTER_X|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT, |
157 |
|
|
0,0,6*6,14); |
158 |
|
|
|
159 |
|
|
alignview->setFocus(); |
160 |
|
|
} |
161 |
|
|
|
162 |
|
|
void MDIChild::showSeqInfo(ClSeq* seq) { |
163 |
|
|
FXString s; |
164 |
|
|
|
165 |
|
|
if (seq!=NULL && seq==alignview->selSeq) { //selection |
166 |
|
|
s.format("%s (%d nt)", seq->name.text(), seq->len); |
167 |
|
|
selseq->setText(s); |
168 |
|
|
if (seq->ins>0 || seq->dels>0) |
169 |
|
|
s.format(" %s range: %d to %d | clipL:%d clipR:%d | gaps: %d dels: %d", |
170 |
|
|
seq->reversed?"-":"+", |
171 |
|
|
seq->clipL+1, seq->len-seq->clipR, |
172 |
|
|
seq->clipL, seq->clipR, |
173 |
|
|
seq->ins, seq->dels); |
174 |
|
|
|
175 |
|
|
else |
176 |
|
|
s.format(" %s range: %d to %d | clipL:%d clipR:%d ", |
177 |
|
|
seq->reversed?"-":"+", |
178 |
|
|
seq->clipL+1, seq->len-seq->clipR, |
179 |
|
|
seq->clipL, seq->clipR); |
180 |
|
|
seqData->setText(s); |
181 |
|
|
//seqComment->setText(seq->comment); |
182 |
|
|
if (seq->group>=0) |
183 |
|
|
s.format("Layout location: %d to %d [group %d]", |
184 |
|
|
seq->cl_xpos+seq->clipL, seq->cl_xpos+seq->len-seq->clipR-1, seq->group); |
185 |
|
|
else |
186 |
|
|
s.format("Layout location: %d to %d", |
187 |
|
|
seq->cl_xpos+seq->clipL, seq->cl_xpos+seq->len-seq->clipR-1); |
188 |
|
|
seqAsmInfo->setText(s); |
189 |
|
|
} |
190 |
|
|
else { //deselect |
191 |
|
|
selseq->setText(" "); |
192 |
|
|
seqData->setText(" "); |
193 |
|
|
seqAsmInfo->setText(" "); |
194 |
|
|
} |
195 |
|
|
int cidx=alignview->getSelCol(); |
196 |
|
|
if (prevColumn==cidx) return; |
197 |
|
|
prevColumn=cidx; |
198 |
|
|
FXString cinfo; |
199 |
|
|
if (cidx>=0) { |
200 |
|
|
ColumnData* c=alignview->getColumnData(cidx); |
201 |
|
|
if (c->letter!=0) { |
202 |
|
|
cinfo.format("Column %d ['%c']: %d layers, %d mismatches ", |
203 |
|
|
cidx+alignview->getXLeft(), c->letter, c->thickness, c->mismatches); |
204 |
|
|
if (c->mismatches>1 && c->thickness>3) { |
205 |
|
|
cinfo+=" [ "; |
206 |
|
|
for (int i=0;i<3;i++) { |
207 |
|
|
if (c->ntdata[i].count>0) { |
208 |
|
|
s.format(" %d%c ", c->ntdata[i].count, c->ntdata[i].letter); |
209 |
|
|
cinfo+=s; |
210 |
|
|
} |
211 |
|
|
} |
212 |
|
|
cinfo+=" ] "; |
213 |
|
|
} |
214 |
|
|
} |
215 |
|
|
else |
216 |
|
|
cinfo.format("Column %d (%d layers)", cidx+alignview->getXLeft(), c->thickness); |
217 |
|
|
columnInfo->setText(cinfo); |
218 |
|
|
} |
219 |
|
|
else { |
220 |
|
|
columnInfo->setText(" "); |
221 |
|
|
} |
222 |
|
|
} |
223 |
|
|
|
224 |
|
|
long MDIChild::onSeqSelect(FXObject*,FXSelector sel,void* ptr){ |
225 |
|
|
showSeqInfo((ClSeq*)ptr); |
226 |
|
|
return 1; |
227 |
|
|
} |
228 |
|
|
|
229 |
|
|
long MDIChild::onCmdClZoom(FXObject*,FXSelector sel,void*){ |
230 |
|
|
FXuint sid=FXSELID(sel); |
231 |
|
|
FXString s; |
232 |
|
|
switch(sid) { |
233 |
|
|
case ID_CLXZOOM: |
234 |
|
|
alignview->ZoomX(((double)sliderZX->getValue())/1000); |
235 |
|
|
s.format("%2.3f",alignview->getZoomX()); |
236 |
|
|
zxLabel->setText(s); |
237 |
|
|
break; |
238 |
|
|
case ID_CLYZOOM: |
239 |
|
|
alignview->ZoomY(((double)sliderZY->getValue())/100); |
240 |
|
|
s.format("%2.2f",alignview->getZoomY()); |
241 |
|
|
zyLabel->setText(s); |
242 |
|
|
break; |
243 |
|
|
} |
244 |
|
|
return 1; |
245 |
|
|
} |
246 |
|
|
|
247 |
|
|
long MDIChild::onColorOption(FXObject*,FXSelector sel,void*){ |
248 |
|
|
FXuint sid=FXSELID(sel); |
249 |
|
|
switch(sid) { |
250 |
|
|
case ID_CSTYLE1: |
251 |
|
|
alignview->setColorStyle(FXGView::csDefault); |
252 |
|
|
break; |
253 |
|
|
case ID_CSTYLE2: |
254 |
|
|
alignview->setColorStyle(FXGView::csDensity); |
255 |
|
|
break; |
256 |
|
|
case ID_CSTYLE3: |
257 |
|
|
alignview->setColorStyle(FXGView::csBaseColor); |
258 |
|
|
break; |
259 |
|
|
} |
260 |
|
|
this->ungrab(); //? bug? |
261 |
|
|
return 1; |
262 |
|
|
} |
263 |
|
|
|
264 |
|
|
// Show up |
265 |
|
|
void MDIChild::create(){ |
266 |
|
|
FXMDIChild::create(); |
267 |
|
|
show(); |
268 |
|
|
} |
269 |
|
|
|
270 |
|
|
|
271 |
|
|
long MDIChild::onRMouseDown(FXObject*,FXSelector,void* ptr) { |
272 |
|
|
FXEvent *ev = (FXEvent*)ptr; |
273 |
|
|
//prevCursor=getApp(); |
274 |
|
|
alignview->setDragCursor(getApp()->getDefaultCursor(DEF_MOVE_CURSOR)); |
275 |
|
|
alignview->grab(); |
276 |
|
|
// While the right-button mouse is down, do zooming |
277 |
|
|
zooming=true; |
278 |
|
|
startZX=alignview->getZoomX(); |
279 |
|
|
startZY=alignview->getZoomY(); |
280 |
|
|
zoomPt.x=ev->win_x; |
281 |
|
|
zoomPt.y=ev->win_y; |
282 |
|
|
return 1; |
283 |
|
|
} |
284 |
|
|
|
285 |
|
|
long MDIChild::onMMouseDown(FXObject*,FXSelector,void* ptr) { |
286 |
|
|
//FXEvent *ev = (FXEvent*)ptr; |
287 |
|
|
//prevCursor=getApp(); |
288 |
|
|
alignview->setDragCursor(getApp()->getDefaultCursor(DEF_MOVE_CURSOR)); |
289 |
|
|
alignview->grab(); |
290 |
|
|
// While the right-button mouse is down, do zooming |
291 |
|
|
panning=true; |
292 |
|
|
//startZX=alignview->getZoomX(); |
293 |
|
|
//startZY=alignview->getZoomY(); |
294 |
|
|
//zoomPt.x=ev->win_x; |
295 |
|
|
//zoomPt.y=ev->win_y; |
296 |
|
|
return 1; |
297 |
|
|
} |
298 |
|
|
|
299 |
|
|
long MDIChild::onMouseMove(FXObject*, FXSelector, void* ptr){ |
300 |
|
|
FXEvent *ev=(FXEvent*)ptr; |
301 |
|
|
if (zooming) { |
302 |
|
|
//compute distance: |
303 |
|
|
//int dx=(ev->win_x-zoomPt.x)*2; |
304 |
|
|
//int dy=(zoomPt.y-ev->win_y)/3; |
305 |
|
|
double newzx = startZX+((double)(ev->win_x-zoomPt.x)*2)/1000; |
306 |
|
|
double newzy = startZY+(((double)(zoomPt.y-ev->win_y))/3)/100; |
307 |
|
|
int minzx, maxzx; |
308 |
|
|
int minzy, maxzy; |
309 |
|
|
sliderZX->getRange(minzx, maxzx); |
310 |
|
|
sliderZY->getRange(minzy, maxzy); |
311 |
|
|
if (newzx*1000<minzx) newzx=(double)minzx/1000; |
312 |
|
|
else |
313 |
|
|
if (newzx*1000>maxzx) newzx=(double)maxzx/1000; |
314 |
|
|
if (newzy*100<minzy) newzy=(double)minzy/100; |
315 |
|
|
else |
316 |
|
|
if (newzy*100>maxzy) newzy=(double)maxzy/100; |
317 |
|
|
if (newzx!=alignview->getZoomX() || |
318 |
|
|
newzy!=alignview->getZoomY()) { |
319 |
|
|
alignview->Zoom(newzx,newzy, |
320 |
|
|
zoomPt.x, zoomPt.y); |
321 |
|
|
FXString s; |
322 |
|
|
sliderZX->setValue((FXint)(newzx*1000)); |
323 |
|
|
sliderZX->forceRefresh(); |
324 |
|
|
s.format("%2.3f",alignview->getZoomX()); |
325 |
|
|
zxLabel->setText(s); |
326 |
|
|
sliderZY->setValue((FXint)(newzy*100)); |
327 |
|
|
sliderZY->forceRefresh(); |
328 |
|
|
s.format("%2.2f",alignview->getZoomY()); |
329 |
|
|
zyLabel->setText(s); |
330 |
|
|
} |
331 |
|
|
} |
332 |
|
|
if (panning) { |
333 |
|
|
alignview->scrollBy((ev->win_x-ev->last_x)*2, (ev->win_y-ev->last_y)*2); |
334 |
|
|
} |
335 |
|
|
return 1; |
336 |
|
|
} |
337 |
|
|
|
338 |
|
|
|
339 |
|
|
long MDIChild::onNoZoom(FXObject*,FXSelector sel,void*) { |
340 |
|
|
sliderZX->setValue(1000); |
341 |
|
|
zxLabel->setText("1.000"); |
342 |
|
|
sliderZY->setValue(100); |
343 |
|
|
zyLabel->setText("1.00"); |
344 |
|
|
alignview->Zoom(1,1); |
345 |
|
|
return 1; |
346 |
|
|
} |
347 |
|
|
|
348 |
|
|
long MDIChild::onMaxZoom(FXObject*,FXSelector sel,void*) { |
349 |
|
|
FXString s; |
350 |
|
|
double newzx, newzy; |
351 |
|
|
alignview->set1pxZoom(); |
352 |
|
|
newzx=alignview->getZoomX(); |
353 |
|
|
newzy=alignview->getZoomY(); |
354 |
|
|
sliderZX->setValue((FXint)(newzx*1000)); |
355 |
|
|
sliderZX->forceRefresh(); |
356 |
|
|
s.format("%2.3f",newzx); |
357 |
|
|
zxLabel->setText(s); |
358 |
|
|
sliderZY->setValue((FXint)(newzy*100)); |
359 |
|
|
sliderZY->forceRefresh(); |
360 |
|
|
s.format("%2.2f",newzy); |
361 |
|
|
zyLabel->setText(s); |
362 |
|
|
return 1; |
363 |
|
|
} |
364 |
|
|
|
365 |
|
|
long MDIChild::onCmdGrps(FXObject*,FXSelector sel,void*) { |
366 |
|
|
FXString ofile=FXFileDialog::getOpenFilename(this,"Open file", //NULL, |
367 |
|
|
"Contig files (*.ace,*.lyt)\nAny file (*)"); |
368 |
|
|
if (!ofile.empty()) loadGroups(ofile); |
369 |
|
|
return 1; |
370 |
|
|
} |
371 |
|
|
|
372 |
|
|
|
373 |
|
|
|
374 |
|
|
long MDIChild::onRMouseUp(FXObject*,FXSelector,void* ptr){ |
375 |
|
|
//FXEvent *ev=(FXEvent*) ptr; |
376 |
|
|
alignview->ungrab(); |
377 |
|
|
zooming=false; |
378 |
|
|
if (!panning) |
379 |
|
|
alignview->setDragCursor(getApp()->getDefaultCursor(DEF_ARROW_CURSOR)); |
380 |
|
|
return 1; |
381 |
|
|
} |
382 |
|
|
|
383 |
|
|
long MDIChild::onMMouseUp(FXObject*,FXSelector,void* ptr){ |
384 |
|
|
alignview->ungrab(); |
385 |
|
|
panning=false; |
386 |
|
|
if (!zooming) |
387 |
|
|
alignview->setDragCursor(getApp()->getDefaultCursor(DEF_ARROW_CURSOR)); |
388 |
|
|
return 1; |
389 |
|
|
} |
390 |
|
|
|
391 |
|
|
|
392 |
|
|
bool MDIChild::openFile(const char* filename) { |
393 |
|
|
//try to recognize the file type and call the appropriate loader |
394 |
|
|
FILE* f; |
395 |
|
|
if ((f=fopen(filename, "r"))==NULL) { |
396 |
|
|
FXMessageBox::error(this,MBOX_OK,"File error", |
397 |
|
|
"Cannot open file '%s'", filename); |
398 |
|
|
} |
399 |
|
|
fclose(f); |
400 |
|
|
FXString fname(filename); |
401 |
|
|
AceParser ap(fname.text()); |
402 |
|
|
if (ap.open()) { |
403 |
|
|
delete layoutparser; |
404 |
|
|
layoutparser=NULL; |
405 |
|
|
layoutparser=new AceParser(fname.text()); |
406 |
|
|
return loadLayoutFile(fname); |
407 |
|
|
} |
408 |
|
|
else { //assumes it's our layout format file |
409 |
|
|
delete layoutparser; |
410 |
|
|
layoutparser=NULL; |
411 |
|
|
layoutparser=new LayoutParser(fname.text()); |
412 |
|
|
} |
413 |
|
|
return loadLayoutFile(fname); |
414 |
|
|
} |
415 |
|
|
|
416 |
|
|
|
417 |
|
|
bool MDIChild::loadLayoutFile(FXString& lytfile) { |
418 |
|
|
if (!layoutparser->open()) { |
419 |
|
|
FXMessageBox::error(this,MBOX_OK,"File error", |
420 |
|
|
"Cannot open file '%s'. Not a valid file?", lytfile.text()); |
421 |
|
|
delete layoutparser; |
422 |
|
|
layoutparser=NULL; |
423 |
|
|
return false; |
424 |
|
|
} |
425 |
|
|
alignview->filetype=layoutparser->getFileType(); |
426 |
|
|
isAce=(alignview->filetype=='A'); |
427 |
|
|
if (!layoutparser->parseContigs() || layoutparser->getNumContigs()==0) { |
428 |
|
|
//if (!layoutparser->parse() || layoutparser->getNumContigs()==0) { |
429 |
|
|
FXMessageBox::error(this,MBOX_OK,"File error", |
430 |
|
|
"Error encountered parsing file '%s'. Not a valid file?", lytfile.text()); |
431 |
|
|
delete layoutparser; |
432 |
|
|
layoutparser=NULL; |
433 |
|
|
return false; |
434 |
|
|
} |
435 |
|
|
file=lytfile; |
436 |
|
|
//file validated. Load align data: |
437 |
|
|
//show all contig labels: |
438 |
|
|
layoutparser->contigsByNumSeqs(); |
439 |
|
|
FXString name; |
440 |
|
|
for (int i=0; i<layoutparser->getNumContigs(); i++) { |
441 |
|
|
LytCtgData* ctg=layoutparser->getContig(i); |
442 |
|
|
name.format("%s (%d seqs, %d nts)", ctg->name, ctg->numseqs, |
443 |
|
|
ctg->len); |
444 |
|
|
selcontig->appendItem(name); |
445 |
|
|
} |
446 |
|
|
//show first contig: |
447 |
|
|
selcontig->setCurrentItem(0); |
448 |
|
|
selContig(0, cbgaps->getCheck()); |
449 |
|
|
if (alignview->HasSeqs()) { |
450 |
|
|
clropt3->enable(); |
451 |
|
|
cbgaps->show(); |
452 |
|
|
} |
453 |
|
|
else { |
454 |
|
|
clropt3->disable(); |
455 |
|
|
cbgaps->hide(); |
456 |
|
|
} |
457 |
|
|
alignview->setColorStyle(FXGView::csDensity); |
458 |
|
|
return true; |
459 |
|
|
} |
460 |
|
|
|
461 |
|
|
void MDIChild::loadGroups(FXString& lytfile) { |
462 |
|
|
//assumes sequences already loaded here |
463 |
|
|
if (alignview->seqlist->Count()==0) { |
464 |
|
|
FXMessageBox::error(this,MBOX_OK,"Action error", |
465 |
|
|
"You need a valid layout file loaded before setting groups."); |
466 |
|
|
return; |
467 |
|
|
} |
468 |
|
|
LayoutParser* lp = new AceParser(lytfile.text()); |
469 |
|
|
if (!lp->open()) { //try ACE first |
470 |
|
|
delete lp; |
471 |
|
|
lp=new LayoutParser(lytfile.text()); |
472 |
|
|
} |
473 |
|
|
else lp->close(); |
474 |
|
|
if (!lp->open() || |
475 |
|
|
!lp->parse()) { |
476 |
|
|
FXMessageBox::error(this,MBOX_OK,"File error", |
477 |
|
|
"Error encountered opening/parsing layout file '%s'. Not a layout file?", lytfile.text()); |
478 |
|
|
delete lp; |
479 |
|
|
return; |
480 |
|
|
} |
481 |
|
|
delete groupHolder; |
482 |
|
|
//groupHolder=NULL; |
483 |
|
|
groupHolder=lp; |
484 |
|
|
assignGroups(); |
485 |
|
|
} |
486 |
|
|
|
487 |
|
|
void MDIChild::assignGroups() { |
488 |
|
|
if (groupHolder==NULL) return; |
489 |
|
|
int numGroups=0; |
490 |
|
|
//we must count only contigs having at least one |
491 |
|
|
//sequence in common with the currently displayed layout |
492 |
|
|
//for each contig, test all component sequences |
493 |
|
|
//groupHolder->parseContigs(); |
494 |
|
|
int nc=groupHolder->getNumContigs(); |
495 |
|
|
for (int i=0; i<nc; i++) { |
496 |
|
|
LytCtgData* ctg=groupHolder->getContig(i); |
497 |
|
|
bool assigned=false; |
498 |
|
|
//for each sequence, see if it's in the viewer's current layout |
499 |
|
|
for (int j=0;j<ctg->numseqs;j++) { |
500 |
|
|
FXString s(ctg->seqs[j]->name); |
501 |
|
|
if (alignview->setSeqGrp(s, numGroups)) assigned=true; |
502 |
|
|
} |
503 |
|
|
if (assigned) numGroups++; //advance to next group |
504 |
|
|
} |
505 |
|
|
if (numGroups>0) { |
506 |
|
|
//alignview->initGrpColors(numGroups); |
507 |
|
|
alignview->update(); |
508 |
|
|
} |
509 |
|
|
else |
510 |
|
|
FXMessageBox::information(this,MBOX_OK,"Information", |
511 |
|
|
"No groups were found for sequences in the selected contig"); |
512 |
|
|
} |
513 |
|
|
|
514 |
|
|
void MDIChild::selContig(int ctgno, bool hideGaps) { |
515 |
|
|
if (ctgno<0 || ctgno>=layoutparser->getNumContigs()) return; |
516 |
|
|
alignview->Clear(); |
517 |
|
|
FXApp* fapp=getApp(); |
518 |
|
|
fapp->beginWaitCursor(); |
519 |
|
|
fapp->forceRefresh(); |
520 |
|
|
|
521 |
|
|
layoutparser->loadContig(ctgno); |
522 |
|
|
LytCtgData* ctg=layoutparser->getContig(ctgno); |
523 |
|
|
char *ctgseq=layoutparser->getContigSeq(ctg); |
524 |
|
|
//now ctgseq contains '*' |
525 |
|
|
//for each position, record how many '*' chars we have on the left |
526 |
|
|
int* ctgrm=NULL; |
527 |
|
|
bool removeGaps=hideGaps; |
528 |
|
|
int ctglen=ctg->len; |
529 |
|
|
if (removeGaps && ctgseq!=NULL) { |
530 |
|
|
int len=strlen(ctgseq); |
531 |
|
|
GMALLOC(ctgrm, (len+1)*sizeof(int)); |
532 |
|
|
int numstars=0; |
533 |
|
|
ctgrm[0]=0; |
534 |
|
|
for (int i=1;i<len;i++) { |
535 |
|
|
numstars += (ctgseq[i-1]=='*'); |
536 |
|
|
ctgrm[i]=numstars; |
537 |
|
|
} |
538 |
|
|
ctgrm[len]=ctgrm[len-1]; |
539 |
|
|
//now remove all the stars from the contig sequence |
540 |
|
|
if (numstars>0) { |
541 |
|
|
char* cleanseq=NULL; |
542 |
|
|
GMALLOC(cleanseq, len-numstars+1); |
543 |
|
|
ctglen-=numstars; |
544 |
|
|
int j=0; |
545 |
|
|
for (int i=0;i<=len;i++) |
546 |
|
|
if (ctgseq[i]!='*') { |
547 |
|
|
cleanseq[j] = ctgseq[i]; |
548 |
|
|
j++; |
549 |
|
|
} |
550 |
|
|
GFREE(ctgseq); |
551 |
|
|
ctgseq=cleanseq; |
552 |
|
|
removeGaps=true; |
553 |
|
|
} |
554 |
|
|
else removeGaps=false; |
555 |
|
|
} |
556 |
|
|
alignview->addContig(ctg->name, ctglen, ctgseq, ctg->offs); |
557 |
|
|
GFREE(ctgseq); |
558 |
|
|
int numseqs=ctg->numseqs; |
559 |
|
|
for (int i=0;i<numseqs;i++) { //reload each read sequence |
560 |
|
|
LytSeqInfo* seq=ctg->seqs[i]; |
561 |
|
|
|
562 |
|
|
char* s=layoutparser->getSeq(seq); |
563 |
|
|
// GMessage("seq %d : %s \n", i, seq->name); |
564 |
|
|
|
565 |
|
|
int slen=0; |
566 |
|
|
if (isAceFile() && (s==NULL || (slen=strlen(s))!=(unsigned int)seq->seglen())) { |
567 |
|
|
FXMessageBox::error(this,MBOX_OK,"File error", |
568 |
|
|
"Error reading sequence '%s' (declared %d, loaded %d). Invalid ACE file?", |
569 |
|
|
seq->name, seq->length(), slen); |
570 |
|
|
delete layoutparser; |
571 |
|
|
layoutparser=NULL; |
572 |
|
|
GFREE(s); |
573 |
|
|
return; |
574 |
|
|
} |
575 |
|
|
if (removeGaps && s!=NULL) { |
576 |
|
|
//shift all coordinates and lengths accordingly, remove gaps |
577 |
|
|
int clpL=seq->left-1; |
578 |
|
|
int clpR=seq->length()-seq->right; |
579 |
|
|
int old_start=seq->offs+clpL; |
580 |
|
|
int old_end=seq->offs+seq->length()-clpR-1; |
581 |
|
|
int new_start=old_start-ctgrm[old_start-1]; |
582 |
|
|
int new_end=old_end-ctgrm[old_end-1]; |
583 |
|
|
//fix interseg coordinates too, when introns are given |
584 |
|
|
// otherwise the "remove gaps" is going to mess up the MSA !! |
585 |
|
|
|
586 |
|
|
for (int g = 0; g < seq->numisegs; g++) { |
587 |
|
|
int prevcoord=seq->intersegs[g].segEnd; |
588 |
|
|
seq->intersegs[g].segEnd-=ctgrm[prevcoord-1]; |
589 |
|
|
prevcoord=seq->intersegs[g].nextStart; |
590 |
|
|
seq->intersegs[g].nextStart-=ctgrm[prevcoord-1]; |
591 |
|
|
} |
592 |
|
|
//now create the cleaned copy of the sequence |
593 |
|
|
char* clnseq=NULL; |
594 |
|
|
int newlen=new_end-new_start+1+clpL+clpR; |
595 |
|
|
GMALLOC(clnseq, sizeof(char)*(newlen+1)); |
596 |
|
|
clnseq[newlen]='\0'; |
597 |
|
|
if (clpL>0) strncpy(clnseq, s, clpL); |
598 |
|
|
int j=clpL; |
599 |
|
|
int numdels=0; |
600 |
|
|
int numins=0; |
601 |
|
|
for (int b=clpL; b<seq->length()-clpR; b++) { |
602 |
|
|
int ctgpos=seq->offs+b; |
603 |
|
|
//delete only if there was also a '*' in the initial contig seq |
604 |
|
|
if (ctgrm[ctgpos]-ctgrm[ctgpos-1]==0) { |
605 |
|
|
clnseq[j] = s[b]; |
606 |
|
|
if (s[b]=='*' || s[b]=='-') { |
607 |
|
|
clnseq[j]='-'; |
608 |
|
|
numins++; |
609 |
|
|
} |
610 |
|
|
j++; |
611 |
|
|
} |
612 |
|
|
else { |
613 |
|
|
if (s[b]!='*' && s[b]!='-') |
614 |
|
|
numdels++; |
615 |
|
|
} |
616 |
|
|
} |
617 |
|
|
clnseq[j]='\0'; |
618 |
|
|
if (clpR>0) strncat(clnseq, s+(seq->length()-clpR), clpR); |
619 |
|
|
GFREE(s); |
620 |
|
|
s=clnseq; |
621 |
|
|
alignview->addSeq(seq->name, newlen, new_start-clpL, seq->reversed, |
622 |
|
|
clpL,clpR,s, numins, numdels); |
623 |
|
|
//alignview->addSeq(seq,s); |
624 |
|
|
} //gaps removal |
625 |
|
|
else { // raw sequence display (with all gaps in place) |
626 |
|
|
/*alignview->addSeq(seq->name, seq->length(), seq->offs, seq->reversed, |
627 |
|
|
seq->left-1,seq->length()-seq->right,s);*/ |
628 |
|
|
alignview->addSeq(seq,s); |
629 |
|
|
} |
630 |
|
|
GFREE(s); |
631 |
|
|
} |
632 |
|
|
alignview->buildLayout(); |
633 |
|
|
assignGroups(); |
634 |
|
|
selseq->clearItems(); |
635 |
|
|
showSeqInfo(NULL); |
636 |
|
|
for (int i=0;i<alignview->seqlist->Count();i++) { |
637 |
|
|
ClSeq* seq=alignview->seqlist->Get(i); |
638 |
|
|
if (seq==alignview->contig) continue; |
639 |
|
|
FXString name; |
640 |
|
|
name.format ("%s (%d nt)", seq->name.text(), seq->len); |
641 |
|
|
selseq->appendItem(name); |
642 |
|
|
} |
643 |
|
|
fapp->endWaitCursor(); |
644 |
|
|
if (alignview->HasSeqs()) { |
645 |
|
|
clropt3->enable(); |
646 |
|
|
cbgaps->show(); |
647 |
|
|
} |
648 |
|
|
else { |
649 |
|
|
clropt3->disable(); |
650 |
|
|
cbgaps->hide(); |
651 |
|
|
} |
652 |
|
|
} |
653 |
|
|
|
654 |
|
|
long MDIChild::onSelContig(FXObject*,FXSelector,void* ptr) { |
655 |
|
|
selContig(selcontig->getCurrentItem(), cbgaps->getCheck()); |
656 |
|
|
return 1; |
657 |
|
|
} |
658 |
|
|
|
659 |
|
|
long MDIChild::onHideGaps(FXObject*,FXSelector,void* ptr) { |
660 |
|
|
selContig(selcontig->getCurrentItem(), cbgaps->getCheck()); |
661 |
|
|
return 1; |
662 |
|
|
} |
663 |
|
|
|
664 |
|
|
|
665 |
|
|
long MDIChild::onSelSeq(FXObject*,FXSelector,void* ptr) { |
666 |
|
|
int seqidx=selseq->getCurrentItem(); |
667 |
|
|
if (seqidx<0) return 1; |
668 |
|
|
ClSeq* seq=alignview->seqlist->Get(seqidx); |
669 |
|
|
alignview->selectSeq(seq, true); |
670 |
|
|
showSeqInfo(seq); |
671 |
|
|
return 1; |
672 |
|
|
} |
673 |
|
|
|
674 |
|
|
long MDIChild::onMaxRestore(FXObject* sender,FXSelector sel,void* ptr) { |
675 |
|
|
FXbool maximized=isMaximized(); |
676 |
|
|
if (wasMaximized!=maximized) { |
677 |
|
|
FXWindow* mainwin=getShell(); |
678 |
|
|
mainwin->handle(mainwin, FXSEL(SEL_COMMAND, ID_MAXRESTORE),ptr); |
679 |
|
|
wasMaximized=maximized; |
680 |
|
|
} |
681 |
|
|
return FXMDIChild::handle(sender,sel,ptr); |
682 |
|
|
} |
683 |
|
|
|
684 |
|
|
MDIChild::~MDIChild() { |
685 |
|
|
delete pop; |
686 |
|
|
delete layoutparser; |
687 |
|
|
delete groupHolder; |
688 |
|
|
//== static members: |
689 |
|
|
numInst--; |
690 |
|
|
if (numInst==0) { |
691 |
|
|
delete ifont; |
692 |
|
|
delete icnDefCS; |
693 |
|
|
delete icnBaseCS; |
694 |
|
|
delete icnDensCS; |
695 |
|
|
} |
696 |
|
|
} |