1 |
/******************************************************************************** |
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 |
} |