Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <stdio.h>
21 : #include <stdlib.h>
22 : #include <tools/config.hxx>
23 : #include <vcl/dibtools.hxx>
24 : #include <vcl/layout.hxx>
25 : #include <vcl/builderfactory.hxx>
26 : #include <sanedlg.hxx>
27 : #include <grid.hxx>
28 : #include <math.h>
29 : #include <sal/macros.h>
30 : #include <rtl/strbuf.hxx>
31 : #include <boost/scoped_array.hpp>
32 : #include "strings.hrc"
33 :
34 : #define PREVIEW_WIDTH 113
35 : #define PREVIEW_HEIGHT 160
36 :
37 : #define RECT_SIZE_PIX 7
38 :
39 : namespace {
40 :
41 0 : void DrawRectangles(vcl::RenderContext& rRenderContext, Point& rUL, Point& rBR)
42 : {
43 : int nMiddleX, nMiddleY;
44 0 : Point aBL, aUR;
45 :
46 0 : aUR = Point(rBR.X(), rUL.Y());
47 0 : aBL = Point(rUL.X(), rBR.Y());
48 0 : nMiddleX = (rBR.X() - rUL.X()) / 2 + rUL.X();
49 0 : nMiddleY = (rBR.Y() - rUL.Y()) / 2 + rUL.Y();
50 :
51 0 : rRenderContext.DrawLine(rUL, aBL);
52 0 : rRenderContext.DrawLine(aBL, rBR);
53 0 : rRenderContext.DrawLine(rBR, aUR);
54 0 : rRenderContext.DrawLine(aUR, rUL);
55 0 : rRenderContext.DrawRect(Rectangle(rUL, Size(RECT_SIZE_PIX,RECT_SIZE_PIX)));
56 0 : rRenderContext.DrawRect(Rectangle(aBL, Size(RECT_SIZE_PIX, -RECT_SIZE_PIX)));
57 0 : rRenderContext.DrawRect(Rectangle(rBR, Size(-RECT_SIZE_PIX, -RECT_SIZE_PIX)));
58 0 : rRenderContext.DrawRect(Rectangle(aUR, Size(-RECT_SIZE_PIX, RECT_SIZE_PIX )));
59 0 : rRenderContext.DrawRect(Rectangle(Point(nMiddleX - RECT_SIZE_PIX / 2, rUL.Y()), Size(RECT_SIZE_PIX, RECT_SIZE_PIX)));
60 0 : rRenderContext.DrawRect(Rectangle(Point(nMiddleX - RECT_SIZE_PIX / 2, rBR.Y()), Size(RECT_SIZE_PIX, -RECT_SIZE_PIX)));
61 0 : rRenderContext.DrawRect(Rectangle(Point(rUL.X(), nMiddleY - RECT_SIZE_PIX / 2), Size(RECT_SIZE_PIX, RECT_SIZE_PIX)));
62 0 : rRenderContext.DrawRect(Rectangle(Point(rBR.X(), nMiddleY - RECT_SIZE_PIX / 2), Size(-RECT_SIZE_PIX, RECT_SIZE_PIX)));
63 0 : }
64 :
65 : }
66 :
67 : class ScanPreview : public vcl::Window
68 : {
69 : private:
70 : enum DragDirection { TopLeft, Top, TopRight, Right, BottomRight, Bottom,
71 : BottomLeft, Left };
72 :
73 : Bitmap maPreviewBitmap;
74 : Rectangle maPreviewRect;
75 : Point maTopLeft, maBottomRight;
76 : Point maMinTopLeft, maMaxBottomRight;
77 : VclPtr<SaneDlg> mpParentDialog;
78 : DragDirection meDragDirection;
79 : bool mbDragEnable;
80 : bool mbDragDrawn;
81 : bool mbIsDragging;
82 :
83 : public:
84 0 : ScanPreview(vcl::Window* pParent, WinBits nStyle)
85 : : Window(pParent, nStyle)
86 : , maMaxBottomRight(PREVIEW_WIDTH, PREVIEW_HEIGHT)
87 : , mpParentDialog(NULL)
88 : , meDragDirection(TopLeft)
89 : , mbDragEnable(false)
90 : , mbDragDrawn(false)
91 0 : , mbIsDragging(false)
92 : {
93 0 : }
94 :
95 0 : virtual ~ScanPreview()
96 0 : {
97 0 : disposeOnce();
98 0 : }
99 :
100 0 : virtual void dispose() SAL_OVERRIDE
101 : {
102 0 : mpParentDialog.clear();
103 0 : vcl::Window::dispose();
104 0 : }
105 :
106 0 : void Init(SaneDlg *pParent)
107 : {
108 0 : mpParentDialog = pParent;
109 0 : }
110 :
111 0 : void ResetForNewScanner()
112 : {
113 0 : maTopLeft = Point();
114 0 : maBottomRight = Point();
115 0 : maMinTopLeft = Point();
116 0 : maMaxBottomRight = Point(PREVIEW_WIDTH, PREVIEW_HEIGHT);
117 0 : }
118 :
119 0 : void EnableDrag()
120 : {
121 0 : mbDragEnable = true;
122 0 : }
123 0 : void DisableDrag()
124 : {
125 0 : mbDragEnable = false;
126 0 : }
127 0 : bool IsDragEnabled()
128 : {
129 0 : return mbDragEnable;
130 : }
131 :
132 : virtual void Paint(vcl::RenderContext& rRenderContext, const Rectangle& rRect) SAL_OVERRIDE;
133 : virtual void MouseButtonDown(const MouseEvent& rMEvt) SAL_OVERRIDE;
134 : virtual void MouseMove(const MouseEvent& rMEvt) SAL_OVERRIDE;
135 : virtual void MouseButtonUp(const MouseEvent& rMEvt) SAL_OVERRIDE;
136 : Point GetPixelPos(const Point& rIn) const;
137 : Point GetLogicPos(const Point& rIn) const;
138 :
139 0 : void GetPreviewLogicRect(Point& rTopLeft, Point &rBottomRight) const
140 : {
141 0 : rTopLeft = GetLogicPos(maTopLeft);
142 0 : rBottomRight = GetLogicPos(maBottomRight);
143 0 : }
144 0 : void GetMaxLogicRect(Point& rTopLeft, Point &rBottomRight) const
145 : {
146 0 : rTopLeft = maMinTopLeft;
147 0 : rBottomRight = maMaxBottomRight;
148 :
149 0 : }
150 0 : void ChangePreviewLogicTopLeftY(long Y)
151 : {
152 0 : Point aPoint(0, Y);
153 0 : aPoint = GetPixelPos(aPoint);
154 0 : maTopLeft.Y() = aPoint.Y();
155 0 : }
156 0 : void ChangePreviewLogicTopLeftX(long X)
157 : {
158 0 : Point aPoint(X, 0);
159 0 : aPoint = GetPixelPos(aPoint);
160 0 : maTopLeft.X() = aPoint.X();
161 0 : }
162 0 : void ChangePreviewLogicBottomRightY(long Y)
163 : {
164 0 : Point aPoint(0, Y);
165 0 : aPoint = GetPixelPos(aPoint);
166 0 : maBottomRight.Y() = aPoint.Y();
167 0 : }
168 0 : void ChangePreviewLogicBottomRightX(long X)
169 : {
170 0 : Point aPoint(X, 0);
171 0 : aPoint = GetPixelPos(aPoint);
172 0 : maBottomRight.X() = aPoint.X();
173 0 : }
174 0 : void SetPreviewLogicRect(const Point& rTopLeft, const Point &rBottomRight)
175 : {
176 0 : maTopLeft = GetPixelPos(rTopLeft);
177 0 : maBottomRight = GetPixelPos(rBottomRight);
178 : maPreviewRect = Rectangle(maTopLeft,
179 0 : Size(maBottomRight.X() - maTopLeft.X(),
180 0 : maBottomRight.Y() - maTopLeft.Y()));
181 0 : }
182 0 : void SetPreviewMaxRect(const Point& rTopLeft, const Point &rBottomRight)
183 : {
184 0 : maMinTopLeft = rTopLeft;
185 0 : maMaxBottomRight = rBottomRight;
186 0 : }
187 : void DrawDrag(vcl::RenderContext& rRenderContext);
188 : void UpdatePreviewBounds();
189 0 : void SetBitmap(SvStream &rStream)
190 : {
191 0 : ReadDIB(maPreviewBitmap, rStream, true);
192 0 : }
193 0 : virtual Size GetOptimalSize() const SAL_OVERRIDE
194 : {
195 0 : Size aSize(LogicToPixel(Size(PREVIEW_WIDTH, PREVIEW_HEIGHT), MAP_APPFONT));
196 0 : aSize.setWidth(aSize.getWidth()+1);
197 0 : aSize.setHeight(aSize.getHeight()+1);
198 0 : return aSize;
199 : }
200 : };
201 :
202 0 : VCL_BUILDER_DECL_FACTORY(ScanPreview)
203 : {
204 0 : WinBits nWinStyle = 0;
205 0 : OString sBorder = VclBuilder::extractCustomProperty(rMap);
206 0 : if (!sBorder.isEmpty())
207 0 : nWinStyle |= WB_BORDER;
208 0 : rRet = VclPtr<ScanPreview>::Create(pParent, nWinStyle);
209 0 : }
210 :
211 0 : SaneDlg::SaneDlg( vcl::Window* pParent, Sane& rSane, bool bScanEnabled ) :
212 : ModalDialog(pParent, "SaneDialog", "modules/scanner/ui/sanedialog.ui"),
213 : mrSane( rSane ),
214 : mbScanEnabled( bScanEnabled ),
215 : mnCurrentOption(0),
216 : mnCurrentElement(0),
217 : mpRange(0),
218 : mfMin(0.0),
219 : mfMax(0.0),
220 0 : doScan(false)
221 : {
222 0 : get(mpOKButton, "ok");
223 0 : get(mpCancelButton, "cancel");
224 0 : get(mpDeviceInfoButton, "deviceInfoButton");
225 0 : get(mpPreviewButton, "previewButton");
226 0 : get(mpScanButton, "scanButton");
227 0 : get(mpButtonOption, "optionsButton");
228 0 : get(mpOptionTitle, "optionTitleLabel");
229 0 : Size aSize(LogicToPixel(Size(130, 102), MAP_APPFONT));
230 0 : mpOptionTitle->set_width_request(aSize.Width());
231 0 : mpOptionTitle->set_height_request(aSize.Height() / 2);
232 0 : get(mpOptionDescTxt, "optionsDescLabel");
233 0 : get(mpVectorTxt, "vectorLabel");
234 0 : get(mpLeftField, "leftSpinbutton");
235 0 : get(mpTopField, "topSpinbutton");
236 0 : get(mpRightField, "rightSpinbutton");
237 0 : get(mpBottomField, "bottomSpinbutton");
238 0 : get(mpDeviceBox, "deviceCombobox");
239 0 : get(mpReslBox, "reslCombobox");
240 0 : get(mpAdvancedBox, "advancedCheckbutton");
241 0 : get(mpVectorBox, "vectorSpinbutton-nospin");
242 0 : get(mpQuantumRangeBox, "quantumRangeCombobox");
243 0 : get(mpStringRangeBox, "stringRangeCombobox");
244 0 : get(mpStringEdit, "stringEntry");
245 0 : get(mpNumericEdit, "numericEntry");
246 0 : get(mpOptionBox, "optionSvTreeListBox");
247 0 : mpOptionBox->set_width_request(aSize.Width());
248 0 : mpOptionBox->set_height_request(aSize.Height());
249 0 : get(mpBoolCheckBox, "boolCheckbutton");
250 0 : get(mpPreview, "preview");
251 0 : mpPreview->Init(this);
252 0 : if( Sane::IsSane() )
253 : {
254 0 : InitDevices(); // opens first sane device
255 0 : DisableOption();
256 0 : InitFields();
257 : }
258 :
259 0 : mpDeviceInfoButton->SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
260 0 : mpPreviewButton->SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
261 0 : mpScanButton->SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
262 0 : mpButtonOption->SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
263 0 : mpDeviceBox->SetSelectHdl( LINK( this, SaneDlg, SelectHdl ) );
264 0 : mpOptionBox->SetSelectHdl( LINK( this, SaneDlg, OptionsBoxSelectHdl ) );
265 0 : mpOKButton->SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
266 0 : mpCancelButton->SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
267 0 : mpBoolCheckBox->SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
268 0 : mpStringEdit->SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
269 0 : mpNumericEdit->SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
270 0 : mpVectorBox->SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
271 0 : mpReslBox->SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
272 0 : mpStringRangeBox->SetSelectHdl( LINK( this, SaneDlg, SelectHdl ) );
273 0 : mpQuantumRangeBox->SetSelectHdl( LINK( this, SaneDlg, SelectHdl ) );
274 0 : mpLeftField->SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
275 0 : mpRightField->SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
276 0 : mpTopField->SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
277 0 : mpBottomField->SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
278 0 : mpAdvancedBox->SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
279 :
280 0 : maOldLink = mrSane.SetReloadOptionsHdl( LINK( this, SaneDlg, ReloadSaneOptionsHdl ) );
281 :
282 0 : mpOptionBox->SetNodeBitmaps(get<FixedImage>("plus")->GetImage(),
283 0 : get<FixedImage>("minus")->GetImage());
284 0 : mpOptionBox->SetStyle(mpOptionBox->GetStyle() |
285 : WB_HASLINES | WB_HASBUTTONS | WB_NOINITIALSELECTION |
286 0 : WB_HASBUTTONSATROOT | WB_HASLINESATROOT);
287 0 : }
288 :
289 0 : SaneDlg::~SaneDlg()
290 : {
291 0 : disposeOnce();
292 0 : }
293 :
294 0 : void SaneDlg::dispose()
295 : {
296 0 : mrSane.SetReloadOptionsHdl(maOldLink);
297 0 : mpOKButton.clear();
298 0 : mpCancelButton.clear();
299 0 : mpDeviceInfoButton.clear();
300 0 : mpPreviewButton.clear();
301 0 : mpScanButton.clear();
302 0 : mpButtonOption.clear();
303 0 : mpOptionTitle.clear();
304 0 : mpOptionDescTxt.clear();
305 0 : mpVectorTxt.clear();
306 0 : mpLeftField.clear();
307 0 : mpTopField.clear();
308 0 : mpRightField.clear();
309 0 : mpBottomField.clear();
310 0 : mpDeviceBox.clear();
311 0 : mpReslBox.clear();
312 0 : mpAdvancedBox.clear();
313 0 : mpVectorBox.clear();
314 0 : mpQuantumRangeBox.clear();
315 0 : mpStringRangeBox.clear();
316 0 : mpBoolCheckBox.clear();
317 0 : mpStringEdit.clear();
318 0 : mpNumericEdit.clear();
319 0 : mpOptionBox.clear();
320 0 : mpPreview.clear();
321 0 : ModalDialog::dispose();
322 0 : }
323 :
324 : namespace {
325 :
326 0 : ResId SaneResId( sal_uInt32 nID )
327 : {
328 0 : static ResMgr* pResMgr = ResMgr::CreateResMgr( "scn" );
329 0 : return ResId( nID, *pResMgr );
330 : }
331 :
332 : }
333 :
334 0 : short SaneDlg::Execute()
335 : {
336 0 : if( ! Sane::IsSane() )
337 : {
338 0 : ScopedVclPtrInstance< MessageDialog > aErrorBox(nullptr, SaneResId(STR_COULD_NOT_BE_INIT));
339 0 : aErrorBox->Execute();
340 0 : return RET_CANCEL;
341 : }
342 0 : LoadState();
343 0 : return ModalDialog::Execute();
344 : }
345 :
346 0 : void SaneDlg::InitDevices()
347 : {
348 0 : if( ! Sane::IsSane() )
349 0 : return;
350 :
351 0 : if( mrSane.IsOpen() )
352 0 : mrSane.Close();
353 0 : mrSane.ReloadDevices();
354 0 : mpDeviceBox->Clear();
355 0 : for (int i = 0; i < Sane::CountDevices(); ++i)
356 0 : mpDeviceBox->InsertEntry(Sane::GetName(i));
357 0 : if( Sane::CountDevices() )
358 : {
359 0 : mrSane.Open(0);
360 0 : mpDeviceBox->SelectEntryPos(0);
361 : }
362 : }
363 :
364 0 : void SaneDlg::InitFields()
365 : {
366 0 : if( ! Sane::IsSane() )
367 0 : return;
368 :
369 : int nOption, i, nValue;
370 : double fValue;
371 0 : bool bSuccess = false;
372 : const char *ppSpecialOptions[] = {
373 : "resolution",
374 : "tl-x",
375 : "tl-y",
376 : "br-x",
377 : "br-y",
378 : "preview"
379 0 : };
380 :
381 0 : mpPreview->EnableDrag();
382 0 : mpReslBox->Clear();
383 0 : Point aTopLeft, aBottomRight;
384 0 : mpPreview->GetPreviewLogicRect(aTopLeft, aBottomRight);
385 0 : Point aMinTopLeft, aMaxBottomRight;
386 0 : mpPreview->GetMaxLogicRect(aMinTopLeft, aMaxBottomRight);
387 0 : mpScanButton->Show( mbScanEnabled );
388 :
389 0 : if( ! mrSane.IsOpen() )
390 0 : return;
391 :
392 : // set Resolution
393 0 : nOption = mrSane.GetOptionByName( "resolution" );
394 0 : if( nOption != -1 )
395 : {
396 : double fRes;
397 :
398 0 : bSuccess = mrSane.GetOptionValue( nOption, fRes );
399 0 : if( bSuccess )
400 : {
401 0 : mpReslBox->Enable( true );
402 :
403 0 : mpReslBox->SetValue( (long)fRes );
404 0 : double *pDouble = NULL;
405 0 : nValue = mrSane.GetRange( nOption, pDouble );
406 0 : if( nValue > -1 )
407 : {
408 0 : if( nValue )
409 : {
410 0 : mpReslBox->SetMin( (long)pDouble[0] );
411 0 : mpReslBox->SetMax( (long)pDouble[ nValue-1 ] );
412 0 : for( i=0; i<nValue; i++ )
413 : {
414 0 : if( i == 0 || i == nValue-1 || ! ( ((int)pDouble[i]) % 20) )
415 0 : mpReslBox->InsertValue( (long)pDouble[i] );
416 : }
417 : }
418 : else
419 : {
420 0 : mpReslBox->SetMin( (long)pDouble[0] );
421 0 : mpReslBox->SetMax( (long)pDouble[1] );
422 0 : mpReslBox->InsertValue( (long)pDouble[0] );
423 : // Can only select 75 and 2400 dpi in Scanner dialogue
424 : // scanner allows random setting of dpi resolution, a slider might be useful
425 : // support that
426 : // workaround: offer at least some more standard dpi resolution between
427 : // min and max value
428 0 : int bGot300 = 0;
429 0 : for ( long nRes = (long) pDouble[0] * 2; nRes < (long) pDouble[1]; nRes = nRes * 2 )
430 : {
431 0 : if ( !bGot300 && nRes > 300 ) {
432 0 : nRes = 300; bGot300 = 1;
433 : }
434 0 : mpReslBox->InsertValue(nRes);
435 : }
436 0 : mpReslBox->InsertValue( (long)pDouble[1] );
437 : }
438 : }
439 : else
440 0 : mpReslBox->Enable( false );
441 0 : delete [] pDouble;
442 : }
443 : }
444 : else
445 0 : mpReslBox->Enable( false );
446 :
447 : // set scan area
448 0 : for( i = 0; i < 4; i++ )
449 : {
450 0 : char const *pOptionName = NULL;
451 0 : MetricField* pField = NULL;
452 0 : switch( i )
453 : {
454 : case 0:
455 0 : pOptionName = "tl-x";
456 0 : pField = mpLeftField;
457 0 : break;
458 : case 1:
459 0 : pOptionName = "tl-y";
460 0 : pField = mpTopField;
461 0 : break;
462 : case 2:
463 0 : pOptionName = "br-x";
464 0 : pField = mpRightField;
465 0 : break;
466 : case 3:
467 0 : pOptionName = "br-y";
468 0 : pField = mpBottomField;
469 : }
470 0 : nOption = pOptionName ? mrSane.GetOptionByName( pOptionName ) : -1;
471 0 : bSuccess = false;
472 0 : if( nOption != -1 )
473 : {
474 0 : bSuccess = mrSane.GetOptionValue( nOption, fValue, 0 );
475 0 : if( bSuccess )
476 : {
477 0 : if( mrSane.GetOptionUnit( nOption ) == SANE_UNIT_MM )
478 : {
479 0 : pField->SetUnit( FUNIT_MM );
480 0 : pField->SetValue( (int)fValue, FUNIT_MM );
481 : }
482 : else // SANE_UNIT_PIXEL
483 : {
484 0 : pField->SetValue( (int)fValue, FUNIT_CUSTOM );
485 0 : pField->SetCustomUnitText(OUString("Pixel"));
486 : }
487 0 : switch( i ) {
488 0 : case 0: aTopLeft.X() = (int)fValue;break;
489 0 : case 1: aTopLeft.Y() = (int)fValue;break;
490 0 : case 2: aBottomRight.X() = (int)fValue;break;
491 0 : case 3: aBottomRight.Y() = (int)fValue;break;
492 : }
493 : }
494 0 : double *pDouble = NULL;
495 0 : nValue = mrSane.GetRange( nOption, pDouble );
496 0 : if( nValue > -1 )
497 : {
498 0 : if( pDouble )
499 : {
500 0 : pField->SetMin( (long)pDouble[0] );
501 0 : if( nValue )
502 0 : pField->SetMax( (long)pDouble[ nValue-1 ] );
503 : else
504 0 : pField->SetMax( (long)pDouble[ 1 ] );
505 0 : delete [] pDouble;
506 : }
507 0 : switch( i ) {
508 0 : case 0: aMinTopLeft.X() = pField->GetMin();break;
509 0 : case 1: aMinTopLeft.Y() = pField->GetMin();break;
510 0 : case 2: aMaxBottomRight.X() = pField->GetMax();break;
511 0 : case 3: aMaxBottomRight.Y() = pField->GetMax();break;
512 : }
513 : }
514 : else
515 : {
516 0 : switch( i ) {
517 0 : case 0: aMinTopLeft.X() = (int)fValue;break;
518 0 : case 1: aMinTopLeft.Y() = (int)fValue;break;
519 0 : case 2: aMaxBottomRight.X() = (int)fValue;break;
520 0 : case 3: aMaxBottomRight.Y() = (int)fValue;break;
521 : }
522 : }
523 0 : pField->Enable( true );
524 : }
525 : else
526 : {
527 0 : mpPreview->DisableDrag();
528 0 : pField->SetMin( 0 );
529 0 : switch( i ) {
530 : case 0:
531 0 : aMinTopLeft.X() = 0;
532 0 : aTopLeft.X() = 0;
533 0 : pField->SetMax( PREVIEW_WIDTH );
534 0 : pField->SetValue( 0 );
535 0 : break;
536 : case 1:
537 0 : aMinTopLeft.Y() = 0;
538 0 : aTopLeft.Y() = 0;
539 0 : pField->SetMax( PREVIEW_HEIGHT );
540 0 : pField->SetValue( 0 );
541 0 : break;
542 : case 2:
543 0 : aMaxBottomRight.X() = PREVIEW_WIDTH;
544 0 : aBottomRight.X() = PREVIEW_WIDTH;
545 0 : pField->SetMax( PREVIEW_WIDTH );
546 0 : pField->SetValue( PREVIEW_WIDTH );
547 0 : break;
548 : case 3:
549 0 : aMaxBottomRight.Y() = PREVIEW_HEIGHT;
550 0 : aBottomRight.Y() = PREVIEW_HEIGHT;
551 0 : pField->SetMax( PREVIEW_HEIGHT );
552 0 : pField->SetValue( PREVIEW_HEIGHT );
553 0 : break;
554 : }
555 0 : pField->Enable( false );
556 : }
557 : }
558 :
559 0 : mpPreview->SetPreviewMaxRect(aMinTopLeft, aMaxBottomRight);
560 0 : mpPreview->SetPreviewLogicRect(aTopLeft, aBottomRight);
561 0 : mpPreview->Invalidate();
562 :
563 : // fill OptionBox
564 0 : mpOptionBox->Clear();
565 0 : SvTreeListEntry* pParentEntry = 0;
566 0 : bool bGroupRejected = false;
567 0 : for( i = 1; i < mrSane.CountOptions(); i++ )
568 : {
569 0 : OUString aOption=mrSane.GetOptionName( i );
570 : bool bInsertAdvanced =
571 0 : (mrSane.GetOptionCap( i ) & SANE_CAP_ADVANCED) == 0 ||
572 0 : mpAdvancedBox->IsChecked();
573 0 : if( mrSane.GetOptionType( i ) == SANE_TYPE_GROUP )
574 : {
575 0 : if( bInsertAdvanced )
576 : {
577 0 : aOption = mrSane.GetOptionTitle( i );
578 0 : pParentEntry = mpOptionBox->InsertEntry( aOption );
579 0 : bGroupRejected = false;
580 : }
581 : else
582 0 : bGroupRejected = true;
583 : }
584 0 : else if( !aOption.isEmpty() &&
585 0 : ! ( mrSane.GetOptionCap( i ) &
586 : (
587 : SANE_CAP_HARD_SELECT |
588 : SANE_CAP_INACTIVE
589 0 : ) ) &&
590 0 : bInsertAdvanced && ! bGroupRejected )
591 : {
592 0 : bool bIsSpecial = false;
593 0 : for( size_t n = 0; !bIsSpecial &&
594 : n < SAL_N_ELEMENTS(ppSpecialOptions); n++ )
595 : {
596 0 : if( aOption == OUString::createFromAscii(ppSpecialOptions[n]) )
597 0 : bIsSpecial=true;
598 : }
599 0 : if( ! bIsSpecial )
600 : {
601 0 : if( pParentEntry )
602 0 : mpOptionBox->InsertEntry( aOption, pParentEntry );
603 : else
604 0 : mpOptionBox->InsertEntry( aOption );
605 : }
606 : }
607 0 : }
608 : }
609 :
610 0 : IMPL_LINK( SaneDlg, ClickBtnHdl, Button*, pButton )
611 : {
612 0 : if( mrSane.IsOpen() )
613 : {
614 0 : if( pButton == mpDeviceInfoButton )
615 : {
616 0 : OUString aString(SaneResId(STR_DEVICE_DESC));
617 0 : aString = aString.replaceFirst( "%s", Sane::GetName( mrSane.GetDeviceNumber() ) );
618 0 : aString = aString.replaceFirst( "%s", Sane::GetVendor( mrSane.GetDeviceNumber() ) );
619 0 : aString = aString.replaceFirst( "%s", Sane::GetModel( mrSane.GetDeviceNumber() ) );
620 0 : aString = aString.replaceFirst( "%s", Sane::GetType( mrSane.GetDeviceNumber() ) );
621 0 : ScopedVclPtrInstance< MessageDialog > aInfoBox(this, aString, VCL_MESSAGE_INFO);
622 0 : aInfoBox->Execute();
623 : }
624 0 : else if( pButton == mpPreviewButton )
625 0 : AcquirePreview();
626 0 : else if( pButton == mpBoolCheckBox )
627 : {
628 : mrSane.SetOptionValue( mnCurrentOption,
629 0 : mpBoolCheckBox->IsChecked() );
630 : }
631 0 : else if( pButton == mpButtonOption )
632 : {
633 :
634 0 : SANE_Value_Type nType = mrSane.GetOptionType( mnCurrentOption );
635 0 : switch( nType )
636 : {
637 : case SANE_TYPE_BUTTON:
638 0 : mrSane.ActivateButtonOption( mnCurrentOption );
639 0 : break;
640 : case SANE_TYPE_FIXED:
641 : case SANE_TYPE_INT:
642 : {
643 0 : int nElements = mrSane.GetOptionElements( mnCurrentOption );
644 0 : boost::scoped_array<double> x(new double[ nElements ]);
645 0 : boost::scoped_array<double> y(new double[ nElements ]);
646 0 : for( int i = 0; i < nElements; i++ )
647 0 : x[ i ] = (double)i;
648 0 : mrSane.GetOptionValue( mnCurrentOption, y.get() );
649 :
650 0 : ScopedVclPtrInstance< GridDialog > aGrid( x.get(), y.get(), nElements, this );
651 0 : aGrid->SetText( mrSane.GetOptionName( mnCurrentOption ) );
652 0 : aGrid->setBoundings( 0, mfMin, nElements, mfMax );
653 0 : if( aGrid->Execute() && aGrid->getNewYValues() )
654 0 : mrSane.SetOptionValue( mnCurrentOption, aGrid->getNewYValues() );
655 : }
656 0 : break;
657 : case SANE_TYPE_BOOL:
658 : case SANE_TYPE_STRING:
659 : case SANE_TYPE_GROUP:
660 0 : break;
661 : }
662 : }
663 0 : else if( pButton == mpAdvancedBox )
664 : {
665 0 : ReloadSaneOptionsHdl( NULL );
666 : }
667 : }
668 0 : if( pButton == mpOKButton || pButton == mpScanButton )
669 : {
670 0 : double fRes = (double)mpReslBox->GetValue();
671 0 : SetAdjustedNumericalValue( "resolution", fRes );
672 0 : UpdateScanArea(true);
673 0 : SaveState();
674 0 : EndDialog( mrSane.IsOpen() ? 1 : 0 );
675 0 : doScan = (pButton == mpScanButton);
676 : }
677 0 : else if( pButton == mpCancelButton )
678 : {
679 0 : mrSane.Close();
680 0 : EndDialog( 0 );
681 : }
682 0 : return 0;
683 : }
684 :
685 0 : IMPL_LINK( SaneDlg, SelectHdl, ListBox*, pListBox )
686 : {
687 0 : if( pListBox == mpDeviceBox && Sane::IsSane() && Sane::CountDevices() )
688 : {
689 0 : int nNewNumber = mpDeviceBox->GetSelectEntryPos();
690 0 : int nOldNumber = mrSane.GetDeviceNumber();
691 0 : if (nNewNumber != nOldNumber)
692 : {
693 0 : mrSane.Close();
694 0 : mrSane.Open(nNewNumber);
695 0 : mpPreview->ResetForNewScanner();
696 0 : InitFields();
697 : }
698 : }
699 0 : if( mrSane.IsOpen() )
700 : {
701 0 : if( pListBox == mpQuantumRangeBox )
702 : {
703 : OString aValue(OUStringToOString(mpQuantumRangeBox->GetSelectEntry(),
704 0 : osl_getThreadTextEncoding()));
705 0 : double fValue = atof(aValue.getStr());
706 0 : mrSane.SetOptionValue( mnCurrentOption, fValue, mnCurrentElement );
707 : }
708 0 : else if( pListBox == mpStringRangeBox )
709 : {
710 0 : mrSane.SetOptionValue( mnCurrentOption, mpStringRangeBox->GetSelectEntry() );
711 : }
712 : }
713 0 : return 0;
714 : }
715 :
716 0 : IMPL_LINK( SaneDlg, OptionsBoxSelectHdl, SvTreeListBox*, pBox )
717 : {
718 0 : if( pBox == mpOptionBox && Sane::IsSane() )
719 : {
720 : OUString aOption =
721 0 : mpOptionBox->GetEntryText( mpOptionBox->FirstSelected() );
722 : int nOption = mrSane.GetOptionByName(OUStringToOString(aOption,
723 0 : osl_getThreadTextEncoding()).getStr());
724 0 : if( nOption != -1 && nOption != mnCurrentOption )
725 : {
726 0 : DisableOption();
727 0 : mnCurrentOption = nOption;
728 0 : mpOptionTitle->SetText( mrSane.GetOptionTitle( mnCurrentOption ) );
729 0 : SANE_Value_Type nType = mrSane.GetOptionType( mnCurrentOption );
730 : SANE_Constraint_Type nConstraint;
731 0 : switch( nType )
732 : {
733 0 : case SANE_TYPE_BOOL: EstablishBoolOption();break;
734 : case SANE_TYPE_STRING:
735 0 : nConstraint = mrSane.GetOptionConstraintType( mnCurrentOption );
736 0 : if( nConstraint == SANE_CONSTRAINT_STRING_LIST )
737 0 : EstablishStringRange();
738 : else
739 0 : EstablishStringOption();
740 0 : break;
741 : case SANE_TYPE_FIXED:
742 : case SANE_TYPE_INT:
743 : {
744 0 : nConstraint = mrSane.GetOptionConstraintType( mnCurrentOption );
745 0 : int nElements = mrSane.GetOptionElements( mnCurrentOption );
746 0 : mnCurrentElement = 0;
747 0 : if( nConstraint == SANE_CONSTRAINT_RANGE ||
748 : nConstraint == SANE_CONSTRAINT_WORD_LIST )
749 0 : EstablishQuantumRange();
750 : else
751 : {
752 0 : mfMin = mfMax = 0.0;
753 0 : EstablishNumericOption();
754 : }
755 0 : if( nElements > 1 )
756 : {
757 0 : if( nElements <= 10 )
758 : {
759 0 : mpVectorBox->SetValue( 1 );
760 0 : mpVectorBox->SetMin( 1 );
761 0 : mpVectorBox->SetMax(
762 0 : mrSane.GetOptionElements( mnCurrentOption ) );
763 0 : mpVectorBox->Show( true );
764 0 : mpVectorTxt->Show( true );
765 : }
766 : else
767 : {
768 0 : DisableOption();
769 : // bring up dialog only on button click
770 0 : EstablishButtonOption();
771 : }
772 : }
773 : }
774 0 : break;
775 : case SANE_TYPE_BUTTON:
776 0 : EstablishButtonOption();
777 0 : break;
778 0 : default: break;
779 : }
780 0 : }
781 : }
782 0 : return 0;
783 : }
784 :
785 0 : IMPL_LINK( SaneDlg, ModifyHdl, Edit*, pEdit )
786 : {
787 0 : if( mrSane.IsOpen() )
788 : {
789 0 : if( pEdit == mpStringEdit )
790 : {
791 0 : mrSane.SetOptionValue( mnCurrentOption, mpStringEdit->GetText() );
792 : }
793 0 : else if( pEdit == mpReslBox )
794 : {
795 0 : double fRes = (double)mpReslBox->GetValue();
796 0 : int nOption = mrSane.GetOptionByName( "resolution" );
797 0 : if( nOption != -1 )
798 : {
799 0 : double* pDouble = NULL;
800 0 : int nValues = mrSane.GetRange( nOption, pDouble );
801 0 : if( nValues > 0 )
802 : {
803 : int i;
804 0 : for( i = 0; i < nValues; i++ )
805 : {
806 0 : if( fRes == pDouble[i] )
807 0 : break;
808 : }
809 0 : if( i >= nValues )
810 0 : fRes = pDouble[0];
811 : }
812 0 : else if( nValues == 0 )
813 : {
814 0 : if( fRes < pDouble[ 0 ] )
815 0 : fRes = pDouble[ 0 ];
816 0 : if( fRes > pDouble[ 1 ] )
817 0 : fRes = pDouble[ 1 ];
818 : }
819 0 : delete[] pDouble;
820 0 : mpReslBox->SetValue( (sal_uLong)fRes );
821 : }
822 : }
823 0 : else if( pEdit == mpNumericEdit )
824 : {
825 : double fValue;
826 0 : OString aContents(OUStringToOString(mpNumericEdit->GetText(),
827 0 : osl_getThreadTextEncoding()));
828 0 : fValue = atof(aContents.getStr());
829 0 : if( mfMin != mfMax && ( fValue < mfMin || fValue > mfMax ) )
830 : {
831 : char pBuf[256];
832 0 : if( fValue < mfMin )
833 0 : fValue = mfMin;
834 0 : else if( fValue > mfMax )
835 0 : fValue = mfMax;
836 0 : sprintf( pBuf, "%g", fValue );
837 0 : mpNumericEdit->SetText( OUString( pBuf, strlen(pBuf), osl_getThreadTextEncoding() ) );
838 : }
839 0 : mrSane.SetOptionValue( mnCurrentOption, fValue, mnCurrentElement );
840 : }
841 0 : else if( pEdit == mpVectorBox )
842 : {
843 0 : mnCurrentElement = mpVectorBox->GetValue()-1;
844 : double fValue;
845 0 : if( mrSane.GetOptionValue( mnCurrentOption, fValue, mnCurrentElement ))
846 : {
847 : char pBuf[256];
848 0 : sprintf( pBuf, "%g", fValue );
849 0 : OUString aValue( pBuf, strlen(pBuf), osl_getThreadTextEncoding() );
850 0 : mpNumericEdit->SetText( aValue );
851 0 : mpQuantumRangeBox->SelectEntry( aValue );
852 : }
853 : }
854 0 : else if( pEdit == mpTopField )
855 : {
856 0 : mpPreview->ChangePreviewLogicTopLeftY(mpTopField->GetValue());
857 0 : mpPreview->Invalidate();
858 : }
859 0 : else if( pEdit == mpLeftField )
860 : {
861 0 : mpPreview->ChangePreviewLogicTopLeftX(mpLeftField->GetValue());
862 0 : mpPreview->Invalidate();
863 : }
864 0 : else if( pEdit == mpBottomField )
865 : {
866 0 : mpPreview->ChangePreviewLogicBottomRightY(mpBottomField->GetValue());
867 0 : mpPreview->Invalidate();
868 : }
869 0 : else if( pEdit == mpRightField )
870 : {
871 0 : mpPreview->ChangePreviewLogicBottomRightX(mpRightField->GetValue());
872 0 : mpPreview->Invalidate();
873 : }
874 : }
875 0 : return 0;
876 : }
877 :
878 0 : IMPL_LINK( SaneDlg, ReloadSaneOptionsHdl, Sane*, /*pSane*/ )
879 : {
880 0 : mnCurrentOption = -1;
881 0 : mnCurrentElement = 0;
882 0 : DisableOption();
883 0 : InitFields();
884 0 : mpPreview->Invalidate();
885 0 : return 0;
886 : }
887 :
888 0 : void SaneDlg::AcquirePreview()
889 : {
890 0 : if( ! mrSane.IsOpen() )
891 0 : return;
892 :
893 0 : UpdateScanArea( true );
894 : // set small resolution for preview
895 0 : double fResl = (double)mpReslBox->GetValue();
896 0 : SetAdjustedNumericalValue( "resolution", 30.0 );
897 :
898 0 : int nOption = mrSane.GetOptionByName( "preview" );
899 0 : if( nOption == -1 )
900 : {
901 0 : OUString aString(SaneResId(STR_SLOW_PREVIEW));
902 0 : ScopedVclPtrInstance< MessageDialog > aBox(this, aString, VCL_MESSAGE_WARNING, VCL_BUTTONS_OK_CANCEL);
903 0 : if (aBox->Execute() == RET_CANCEL)
904 0 : return;
905 : }
906 : else
907 0 : mrSane.SetOptionValue( nOption, true );
908 :
909 0 : BitmapTransporter aTransporter;
910 0 : if( ! mrSane.Start( aTransporter ) )
911 : {
912 0 : ScopedVclPtrInstance< MessageDialog > aErrorBox(this, SaneResId(STR_ERROR_SCAN));
913 0 : aErrorBox->Execute();
914 : }
915 : else
916 : {
917 : #if OSL_DEBUG_LEVEL > 1
918 : aTransporter.getStream().Seek( STREAM_SEEK_TO_END );
919 : fprintf( stderr, "Previewbitmapstream contains %d bytes\n", (int)aTransporter.getStream().Tell() );
920 : #endif
921 0 : aTransporter.getStream().Seek( STREAM_SEEK_TO_BEGIN );
922 0 : mpPreview->SetBitmap(aTransporter.getStream());
923 : }
924 :
925 0 : SetAdjustedNumericalValue( "resolution", fResl );
926 0 : mpReslBox->SetValue( (sal_uLong)fResl );
927 :
928 0 : mpPreview->UpdatePreviewBounds();
929 0 : mpPreview->Invalidate();
930 : }
931 :
932 0 : void ScanPreview::UpdatePreviewBounds()
933 : {
934 0 : if( mbDragEnable )
935 : {
936 : maPreviewRect = Rectangle( maTopLeft,
937 0 : Size( maBottomRight.X() - maTopLeft.X(),
938 0 : maBottomRight.Y() - maTopLeft.Y() )
939 0 : );
940 : }
941 : else
942 : {
943 0 : Size aBMSize( maPreviewBitmap.GetSizePixel() );
944 0 : if( aBMSize.Width() > aBMSize.Height() && aBMSize.Width() )
945 : {
946 0 : int nVHeight = (maBottomRight.X() - maTopLeft.X()) * aBMSize.Height() / aBMSize.Width();
947 0 : maPreviewRect = Rectangle( Point( maTopLeft.X(), ( maTopLeft.Y() + maBottomRight.Y() )/2 - nVHeight/2 ),
948 0 : Size( maBottomRight.X() - maTopLeft.X(),
949 0 : nVHeight ) );
950 : }
951 0 : else if (aBMSize.Height())
952 : {
953 0 : int nVWidth = (maBottomRight.Y() - maTopLeft.Y()) * aBMSize.Width() / aBMSize.Height();
954 0 : maPreviewRect = Rectangle( Point( ( maTopLeft.X() + maBottomRight.X() )/2 - nVWidth/2, maTopLeft.Y() ),
955 : Size( nVWidth,
956 0 : maBottomRight.Y() - maTopLeft.Y() ) );
957 : }
958 : }
959 0 : }
960 :
961 0 : void ScanPreview::Paint(vcl::RenderContext& rRenderContext, const Rectangle& rRect)
962 : {
963 0 : Window::Paint(rRenderContext, rRect);
964 0 : rRenderContext.SetMapMode(MAP_APPFONT);
965 0 : rRenderContext.SetFillColor(Color(COL_WHITE));
966 0 : rRenderContext.SetLineColor(Color(COL_WHITE));
967 : rRenderContext.DrawRect(Rectangle(Point(0, 0),
968 0 : Size(PREVIEW_WIDTH, PREVIEW_HEIGHT)));
969 0 : rRenderContext.SetMapMode(MapMode(MAP_PIXEL));
970 : // check for sane values
971 0 : rRenderContext.DrawBitmap(maPreviewRect.TopLeft(), maPreviewRect.GetSize(), maPreviewBitmap);
972 :
973 0 : mbDragDrawn = false;
974 0 : DrawDrag(rRenderContext);
975 0 : }
976 :
977 0 : void SaneDlg::DisableOption()
978 : {
979 0 : mpBoolCheckBox->Show( false );
980 0 : mpStringEdit->Show( false );
981 0 : mpNumericEdit->Show( false );
982 0 : mpQuantumRangeBox->Show( false );
983 0 : mpStringRangeBox->Show( false );
984 0 : mpButtonOption->Show( false );
985 0 : mpVectorBox->Show( false );
986 0 : mpVectorTxt->Show( false );
987 0 : mpOptionDescTxt->Show( false );
988 0 : }
989 :
990 0 : void SaneDlg::EstablishBoolOption()
991 : {
992 : bool bSuccess, bValue;
993 :
994 0 : bSuccess = mrSane.GetOptionValue( mnCurrentOption, bValue );
995 0 : if( bSuccess )
996 : {
997 0 : mpBoolCheckBox->SetText( mrSane.GetOptionName( mnCurrentOption ) );
998 0 : mpBoolCheckBox->Check( bValue );
999 0 : mpBoolCheckBox->Show( true );
1000 : }
1001 0 : }
1002 :
1003 0 : void SaneDlg::EstablishStringOption()
1004 : {
1005 : bool bSuccess;
1006 0 : OString aValue;
1007 :
1008 0 : bSuccess = mrSane.GetOptionValue( mnCurrentOption, aValue );
1009 0 : if( bSuccess )
1010 : {
1011 0 : mpOptionDescTxt->SetText( mrSane.GetOptionName( mnCurrentOption ) );
1012 0 : mpOptionDescTxt->Show( true );
1013 0 : mpStringEdit->SetText(OStringToOUString(aValue, osl_getThreadTextEncoding()));
1014 0 : mpStringEdit->Show( true );
1015 0 : }
1016 0 : }
1017 :
1018 0 : void SaneDlg::EstablishStringRange()
1019 : {
1020 0 : const char** ppStrings = mrSane.GetStringConstraint( mnCurrentOption );
1021 0 : mpStringRangeBox->Clear();
1022 0 : for( int i = 0; ppStrings[i] != 0; i++ )
1023 0 : mpStringRangeBox->InsertEntry( OUString( ppStrings[i], strlen(ppStrings[i]), osl_getThreadTextEncoding() ) );
1024 0 : OString aValue;
1025 0 : mrSane.GetOptionValue( mnCurrentOption, aValue );
1026 0 : mpStringRangeBox->SelectEntry(OStringToOUString(aValue, osl_getThreadTextEncoding()));
1027 0 : mpStringRangeBox->Show( true );
1028 0 : mpOptionDescTxt->SetText( mrSane.GetOptionName( mnCurrentOption ) );
1029 0 : mpOptionDescTxt->Show( true );
1030 0 : }
1031 :
1032 0 : void SaneDlg::EstablishQuantumRange()
1033 : {
1034 0 : if( mpRange )
1035 : {
1036 0 : delete [] mpRange;
1037 0 : mpRange = 0;
1038 : }
1039 0 : int nValues = mrSane.GetRange( mnCurrentOption, mpRange );
1040 0 : if( nValues == 0 )
1041 : {
1042 0 : mfMin = mpRange[ 0 ];
1043 0 : mfMax = mpRange[ 1 ];
1044 0 : delete [] mpRange;
1045 0 : mpRange = 0;
1046 0 : EstablishNumericOption();
1047 : }
1048 0 : else if( nValues > 0 )
1049 : {
1050 : char pBuf[ 256 ];
1051 0 : mpQuantumRangeBox->Clear();
1052 0 : mfMin = mpRange[ 0 ];
1053 0 : mfMax = mpRange[ nValues-1 ];
1054 0 : for( int i = 0; i < nValues; i++ )
1055 : {
1056 0 : sprintf( pBuf, "%g", mpRange[ i ] );
1057 0 : mpQuantumRangeBox->InsertEntry( OUString( pBuf, strlen(pBuf), osl_getThreadTextEncoding() ) );
1058 : }
1059 : double fValue;
1060 0 : if( mrSane.GetOptionValue( mnCurrentOption, fValue, mnCurrentElement ) )
1061 : {
1062 0 : sprintf( pBuf, "%g", fValue );
1063 0 : mpQuantumRangeBox->SelectEntry( OUString( pBuf, strlen(pBuf), osl_getThreadTextEncoding() ) );
1064 : }
1065 0 : mpQuantumRangeBox->Show( true );
1066 0 : OUString aText( mrSane.GetOptionName( mnCurrentOption ) );
1067 0 : aText += " ";
1068 0 : aText += mrSane.GetOptionUnitName( mnCurrentOption );
1069 0 : mpOptionDescTxt->SetText( aText );
1070 0 : mpOptionDescTxt->Show( true );
1071 : }
1072 0 : }
1073 :
1074 0 : void SaneDlg::EstablishNumericOption()
1075 : {
1076 : bool bSuccess;
1077 : double fValue;
1078 :
1079 0 : bSuccess = mrSane.GetOptionValue( mnCurrentOption, fValue );
1080 0 : if( ! bSuccess )
1081 0 : return;
1082 :
1083 : char pBuf[256];
1084 0 : OUString aText( mrSane.GetOptionName( mnCurrentOption ) );
1085 0 : aText += " ";
1086 0 : aText += mrSane.GetOptionUnitName( mnCurrentOption );
1087 0 : if( mfMin != mfMax )
1088 : {
1089 0 : sprintf( pBuf, " < %g ; %g >", mfMin, mfMax );
1090 0 : aText += OUString( pBuf, strlen(pBuf), osl_getThreadTextEncoding() );
1091 : }
1092 0 : mpOptionDescTxt->SetText( aText );
1093 0 : mpOptionDescTxt->Show( true );
1094 0 : sprintf( pBuf, "%g", fValue );
1095 0 : mpNumericEdit->SetText( OUString( pBuf, strlen(pBuf), osl_getThreadTextEncoding() ) );
1096 0 : mpNumericEdit->Show( true );
1097 : }
1098 :
1099 0 : void SaneDlg::EstablishButtonOption()
1100 : {
1101 0 : mpOptionDescTxt->SetText( mrSane.GetOptionName( mnCurrentOption ) );
1102 0 : mpOptionDescTxt->Show( true );
1103 0 : mpButtonOption->Show( true );
1104 0 : }
1105 :
1106 0 : void ScanPreview::MouseMove(const MouseEvent& rMEvt)
1107 : {
1108 0 : if( mbIsDragging )
1109 : {
1110 0 : Point aMousePos = rMEvt.GetPosPixel();
1111 : // move into valid area
1112 0 : Point aLogicPos = GetLogicPos( aMousePos );
1113 0 : aMousePos = GetPixelPos( aLogicPos );
1114 0 : switch( meDragDirection )
1115 : {
1116 0 : case TopLeft: maTopLeft = aMousePos; break;
1117 0 : case Top: maTopLeft.Y() = aMousePos.Y(); break;
1118 : case TopRight:
1119 0 : maTopLeft.Y() = aMousePos.Y();
1120 0 : maBottomRight.X() = aMousePos.X();
1121 0 : break;
1122 0 : case Right: maBottomRight.X() = aMousePos.X(); break;
1123 0 : case BottomRight: maBottomRight = aMousePos; break;
1124 0 : case Bottom: maBottomRight.Y() = aMousePos.Y(); break;
1125 : case BottomLeft:
1126 0 : maTopLeft.X() = aMousePos.X();
1127 0 : maBottomRight.Y() = aMousePos.Y();
1128 0 : break;
1129 0 : case Left: maTopLeft.X() = aMousePos.X(); break;
1130 0 : default: break;
1131 : }
1132 : int nSwap;
1133 0 : if( maTopLeft.X() > maBottomRight.X() )
1134 : {
1135 0 : nSwap = maTopLeft.X();
1136 0 : maTopLeft.X() = maBottomRight.X();
1137 0 : maBottomRight.X() = nSwap;
1138 : }
1139 0 : if( maTopLeft.Y() > maBottomRight.Y() )
1140 : {
1141 0 : nSwap = maTopLeft.Y();
1142 0 : maTopLeft.Y() = maBottomRight.Y();
1143 0 : maBottomRight.Y() = nSwap;
1144 : }
1145 0 : Invalidate();
1146 0 : mpParentDialog->UpdateScanArea(false);
1147 : }
1148 0 : Window::MouseMove( rMEvt );
1149 0 : }
1150 :
1151 0 : void ScanPreview::MouseButtonDown( const MouseEvent& rMEvt )
1152 : {
1153 0 : Point aMousePixel = rMEvt.GetPosPixel();
1154 :
1155 0 : if( ! mbIsDragging && mbDragEnable )
1156 : {
1157 0 : int nMiddleX = ( maBottomRight.X() - maTopLeft.X() ) / 2 - RECT_SIZE_PIX/2 + maTopLeft.X();
1158 0 : int nMiddleY = ( maBottomRight.Y() - maTopLeft.Y() ) / 2 - RECT_SIZE_PIX/2 + maTopLeft.Y();
1159 0 : if( aMousePixel.Y() >= maTopLeft.Y() &&
1160 0 : aMousePixel.Y() < maTopLeft.Y() + RECT_SIZE_PIX )
1161 : {
1162 0 : if( aMousePixel.X() >= maTopLeft.X() &&
1163 0 : aMousePixel.X() < maTopLeft.X() + RECT_SIZE_PIX )
1164 : {
1165 0 : meDragDirection = TopLeft;
1166 0 : aMousePixel = maTopLeft;
1167 0 : mbIsDragging = true;
1168 : }
1169 0 : else if( aMousePixel.X() >= nMiddleX &&
1170 0 : aMousePixel.X() < nMiddleX + RECT_SIZE_PIX )
1171 : {
1172 0 : meDragDirection = Top;
1173 0 : aMousePixel.Y() = maTopLeft.Y();
1174 0 : mbIsDragging = true;
1175 : }
1176 0 : else if( aMousePixel.X() > maBottomRight.X() - RECT_SIZE_PIX &&
1177 0 : aMousePixel.X() <= maBottomRight.X() )
1178 : {
1179 0 : meDragDirection = TopRight;
1180 0 : aMousePixel = Point( maBottomRight.X(), maTopLeft.Y() );
1181 0 : mbIsDragging = true;
1182 : }
1183 : }
1184 0 : else if( aMousePixel.Y() >= nMiddleY &&
1185 0 : aMousePixel.Y() < nMiddleY + RECT_SIZE_PIX )
1186 : {
1187 0 : if( aMousePixel.X() >= maTopLeft.X() &&
1188 0 : aMousePixel.X() < maTopLeft.X() + RECT_SIZE_PIX )
1189 : {
1190 0 : meDragDirection = Left;
1191 0 : aMousePixel.X() = maTopLeft.X();
1192 0 : mbIsDragging = true;
1193 : }
1194 0 : else if( aMousePixel.X() > maBottomRight.X() - RECT_SIZE_PIX &&
1195 0 : aMousePixel.X() <= maBottomRight.X() )
1196 : {
1197 0 : meDragDirection = Right;
1198 0 : aMousePixel.X() = maBottomRight.X();
1199 0 : mbIsDragging = true;
1200 : }
1201 : }
1202 0 : else if( aMousePixel.Y() <= maBottomRight.Y() &&
1203 0 : aMousePixel.Y() > maBottomRight.Y() - RECT_SIZE_PIX )
1204 : {
1205 0 : if( aMousePixel.X() >= maTopLeft.X() &&
1206 0 : aMousePixel.X() < maTopLeft.X() + RECT_SIZE_PIX )
1207 : {
1208 0 : meDragDirection = BottomLeft;
1209 0 : aMousePixel = Point( maTopLeft.X(), maBottomRight.Y() );
1210 0 : mbIsDragging = true;
1211 : }
1212 0 : else if( aMousePixel.X() >= nMiddleX &&
1213 0 : aMousePixel.X() < nMiddleX + RECT_SIZE_PIX )
1214 : {
1215 0 : meDragDirection = Bottom;
1216 0 : aMousePixel.Y() = maBottomRight.Y();
1217 0 : mbIsDragging = true;
1218 : }
1219 0 : else if( aMousePixel.X() > maBottomRight.X() - RECT_SIZE_PIX &&
1220 0 : aMousePixel.X() <= maBottomRight.X() )
1221 : {
1222 0 : meDragDirection = BottomRight;
1223 0 : aMousePixel = maBottomRight;
1224 0 : mbIsDragging = true;
1225 : }
1226 : }
1227 : }
1228 0 : if( mbIsDragging )
1229 : {
1230 0 : SetPointerPosPixel( aMousePixel );
1231 0 : Invalidate();
1232 : }
1233 0 : Window::MouseButtonDown( rMEvt );
1234 0 : }
1235 :
1236 0 : void ScanPreview::MouseButtonUp( const MouseEvent& rMEvt )
1237 : {
1238 0 : if( mbIsDragging )
1239 : {
1240 0 : mpParentDialog->UpdateScanArea(true);
1241 : }
1242 0 : mbIsDragging = false;
1243 :
1244 0 : Window::MouseButtonUp( rMEvt );
1245 0 : }
1246 :
1247 0 : void ScanPreview::DrawDrag(vcl::RenderContext& rRenderContext)
1248 : {
1249 0 : static Point aLastUL, aLastBR;
1250 :
1251 0 : if (!mbDragEnable)
1252 0 : return;
1253 :
1254 0 : RasterOp eROP = rRenderContext.GetRasterOp();
1255 0 : rRenderContext.SetRasterOp(ROP_INVERT);
1256 0 : rRenderContext.SetMapMode(MapMode(MAP_PIXEL));
1257 :
1258 0 : if (mbDragDrawn)
1259 0 : DrawRectangles(rRenderContext, aLastUL, aLastBR);
1260 :
1261 0 : aLastUL = maTopLeft;
1262 0 : aLastBR = maBottomRight;
1263 0 : DrawRectangles(rRenderContext, maTopLeft, maBottomRight);
1264 :
1265 0 : mbDragDrawn = true;
1266 0 : rRenderContext.SetRasterOp(eROP);
1267 0 : rRenderContext.SetMapMode(MAP_APPFONT);
1268 : }
1269 :
1270 0 : Point ScanPreview::GetPixelPos( const Point& rIn) const
1271 : {
1272 : Point aConvert(
1273 0 : ( ( rIn.X() * PREVIEW_WIDTH ) /
1274 0 : ( maMaxBottomRight.X() - maMinTopLeft.X() ) )
1275 : ,
1276 0 : ( ( rIn.Y() * PREVIEW_HEIGHT )
1277 0 : / ( maMaxBottomRight.Y() - maMinTopLeft.Y() ) )
1278 0 : );
1279 :
1280 0 : return LogicToPixel(aConvert, MAP_APPFONT);
1281 : }
1282 :
1283 0 : Point ScanPreview::GetLogicPos(const Point& rIn) const
1284 : {
1285 0 : Point aConvert = PixelToLogic(rIn, MAP_APPFONT);
1286 0 : if( aConvert.X() < 0 )
1287 0 : aConvert.X() = 0;
1288 0 : if( aConvert.X() >= PREVIEW_WIDTH )
1289 0 : aConvert.X() = PREVIEW_WIDTH-1;
1290 0 : if( aConvert.Y() < 0 )
1291 0 : aConvert.Y() = 0;
1292 0 : if( aConvert.Y() >= PREVIEW_HEIGHT )
1293 0 : aConvert.Y() = PREVIEW_HEIGHT-1;
1294 :
1295 0 : aConvert.X() *= ( maMaxBottomRight.X() - maMinTopLeft.X() );
1296 0 : aConvert.X() /= PREVIEW_WIDTH;
1297 0 : aConvert.Y() *= ( maMaxBottomRight.Y() - maMinTopLeft.Y() );
1298 0 : aConvert.Y() /= PREVIEW_HEIGHT;
1299 0 : return aConvert;
1300 : }
1301 :
1302 0 : void SaneDlg::UpdateScanArea(bool bSend)
1303 : {
1304 0 : if (!mpPreview->IsDragEnabled())
1305 0 : return;
1306 :
1307 0 : Point aUL, aBR;
1308 0 : mpPreview->GetPreviewLogicRect(aUL, aBR);
1309 :
1310 0 : mpLeftField->SetValue( aUL.X() );
1311 0 : mpTopField->SetValue( aUL.Y() );
1312 0 : mpRightField->SetValue( aBR.X() );
1313 0 : mpBottomField->SetValue( aBR.Y() );
1314 :
1315 0 : if (!bSend)
1316 0 : return;
1317 :
1318 0 : if( mrSane.IsOpen() )
1319 : {
1320 0 : SetAdjustedNumericalValue( "tl-x", (double)aUL.X() );
1321 0 : SetAdjustedNumericalValue( "tl-y", (double)aUL.Y() );
1322 0 : SetAdjustedNumericalValue( "br-x", (double)aBR.X() );
1323 0 : SetAdjustedNumericalValue( "br-y", (double)aBR.Y() );
1324 : }
1325 : }
1326 :
1327 0 : bool SaneDlg::LoadState()
1328 : {
1329 : int i;
1330 :
1331 0 : if( ! Sane::IsSane() )
1332 0 : return false;
1333 :
1334 0 : const char* pEnv = getenv("HOME");
1335 0 : OUString aFileName = pEnv ? OUString(pEnv, strlen(pEnv), osl_getThreadTextEncoding() ) : OUString();
1336 0 : aFileName += "/.so_sane_state";
1337 0 : Config aConfig( aFileName );
1338 0 : if( ! aConfig.HasGroup( "SANE" ) )
1339 0 : return false;
1340 :
1341 0 : aConfig.SetGroup( "SANE" );
1342 0 : OString aString = aConfig.ReadKey( "SO_LastSaneDevice" );
1343 0 : for( i = 0; i < Sane::CountDevices() && !aString.equals(OUStringToOString(Sane::GetName(i), osl_getThreadTextEncoding())); i++ ) ;
1344 0 : if( i == Sane::CountDevices() )
1345 0 : return false;
1346 :
1347 0 : mrSane.Close();
1348 0 : mrSane.Open( aString.getStr() );
1349 :
1350 0 : DisableOption();
1351 0 : InitFields();
1352 :
1353 0 : if( mrSane.IsOpen() )
1354 : {
1355 0 : int iMax = aConfig.GetKeyCount();
1356 0 : for (i = 0; i < iMax; ++i)
1357 : {
1358 0 : aString = aConfig.GetKeyName( i );
1359 0 : OString aValue = aConfig.ReadKey( i );
1360 0 : int nOption = mrSane.GetOptionByName( aString.getStr() );
1361 0 : if( nOption == -1 )
1362 0 : continue;
1363 :
1364 0 : if (aValue.startsWith("BOOL="))
1365 : {
1366 0 : aValue = aValue.copy(RTL_CONSTASCII_LENGTH("BOOL="));
1367 0 : bool aBOOL = aValue.toInt32() != 0;
1368 0 : mrSane.SetOptionValue( nOption, aBOOL );
1369 : }
1370 0 : else if (aValue.startsWith("STRING="))
1371 : {
1372 0 : aValue = aValue.copy(RTL_CONSTASCII_LENGTH("STRING="));
1373 0 : mrSane.SetOptionValue(nOption,OStringToOUString(aValue, osl_getThreadTextEncoding()) );
1374 : }
1375 0 : else if (aValue.startsWith("NUMERIC="))
1376 : {
1377 0 : aValue = aValue.copy(RTL_CONSTASCII_LENGTH("NUMERIC="));
1378 :
1379 0 : sal_Int32 nIndex = 0;
1380 0 : int n = 0;
1381 0 : do
1382 : {
1383 0 : OString aSub = aValue.getToken(0, ':', nIndex);
1384 0 : double fValue=0.0;
1385 0 : sscanf(aSub.getStr(), "%lg", &fValue);
1386 0 : SetAdjustedNumericalValue(aString.getStr(), fValue, n++);
1387 : }
1388 0 : while ( nIndex >= 0 );
1389 : }
1390 0 : }
1391 : }
1392 :
1393 0 : DisableOption();
1394 0 : InitFields();
1395 :
1396 0 : return true;
1397 : }
1398 :
1399 0 : void SaneDlg::SaveState()
1400 : {
1401 0 : if( ! Sane::IsSane() )
1402 0 : return;
1403 :
1404 0 : const char* pEnv = getenv( "HOME" );
1405 0 : OUString aFileName;
1406 :
1407 0 : if( pEnv )
1408 0 : aFileName = OUString::createFromAscii(pEnv) + "/.so_sane_state";
1409 : else
1410 0 : aFileName = OStringToOUString("", osl_getThreadTextEncoding()) + "/.so_sane_state";
1411 :
1412 0 : Config aConfig( aFileName );
1413 0 : aConfig.DeleteGroup( "SANE" );
1414 0 : aConfig.SetGroup( "SANE" );
1415 : aConfig.WriteKey( "SO_LastSANEDevice",
1416 0 : OUStringToOString(mpDeviceBox->GetSelectEntry(), RTL_TEXTENCODING_UTF8) );
1417 :
1418 : static char const* pSaveOptions[] = {
1419 : "resolution",
1420 : "tl-x",
1421 : "tl-y",
1422 : "br-x",
1423 : "br-y"
1424 : };
1425 0 : for( size_t i = 0; i < SAL_N_ELEMENTS(pSaveOptions); ++i )
1426 : {
1427 0 : OString aOption = pSaveOptions[i];
1428 0 : int nOption = mrSane.GetOptionByName( pSaveOptions[i] );
1429 0 : if( nOption > -1 )
1430 : {
1431 0 : SANE_Value_Type nType = mrSane.GetOptionType( nOption );
1432 0 : switch( nType )
1433 : {
1434 : case SANE_TYPE_BOOL:
1435 : {
1436 : bool bValue;
1437 0 : if( mrSane.GetOptionValue( nOption, bValue ) )
1438 : {
1439 0 : OStringBuffer aString("BOOL=");
1440 0 : aString.append(static_cast<sal_Int32>(bValue));
1441 0 : aConfig.WriteKey(aOption, aString.makeStringAndClear());
1442 : }
1443 : }
1444 0 : break;
1445 : case SANE_TYPE_STRING:
1446 : {
1447 0 : OString aValue;
1448 0 : if( mrSane.GetOptionValue( nOption, aValue ) )
1449 : {
1450 0 : OStringBuffer aString("STRING=");
1451 0 : aString.append(aValue);
1452 0 : aConfig.WriteKey( aOption, aString.makeStringAndClear() );
1453 0 : }
1454 : }
1455 0 : break;
1456 : case SANE_TYPE_FIXED:
1457 : case SANE_TYPE_INT:
1458 : {
1459 0 : OStringBuffer aString("NUMERIC=");
1460 : double fValue;
1461 : char buf[256];
1462 : int n;
1463 :
1464 0 : for( n = 0; n < mrSane.GetOptionElements( nOption ); n++ )
1465 : {
1466 0 : if( ! mrSane.GetOptionValue( nOption, fValue, n ) )
1467 0 : break;
1468 0 : if( n > 0 )
1469 0 : aString.append(':');
1470 0 : sprintf( buf, "%lg", fValue );
1471 0 : aString.append(buf);
1472 : }
1473 0 : if( n >= mrSane.GetOptionElements( nOption ) )
1474 0 : aConfig.WriteKey( aOption, aString.makeStringAndClear() );
1475 : }
1476 0 : break;
1477 : default:
1478 0 : break;
1479 : }
1480 : }
1481 0 : }
1482 : }
1483 :
1484 0 : bool SaneDlg::SetAdjustedNumericalValue(
1485 : const char* pOption,
1486 : double fValue,
1487 : int nElement )
1488 : {
1489 : int nOption;
1490 0 : if( ! Sane::IsSane() || ! mrSane.IsOpen() || ( nOption = mrSane.GetOptionByName( pOption ) ) == -1 )
1491 0 : return false;
1492 :
1493 0 : if( nElement < 0 || nElement >= mrSane.GetOptionElements( nOption ) )
1494 0 : return false;
1495 :
1496 0 : double* pValues = NULL;
1497 : int nValues;
1498 0 : if( ( nValues = mrSane.GetRange( nOption, pValues ) ) < 0 )
1499 : {
1500 0 : delete [] pValues;
1501 0 : return false;
1502 : }
1503 :
1504 : #if OSL_DEBUG_LEVEL > 1
1505 : fprintf( stderr, "SaneDlg::SetAdjustedNumericalValue( \"%s\", %lg ) ",
1506 : pOption, fValue );
1507 : #endif
1508 :
1509 0 : if( nValues )
1510 : {
1511 0 : int nNearest = 0;
1512 0 : double fNearest = 1e6;
1513 0 : for( int i = 0; i < nValues; i++ )
1514 : {
1515 0 : if( fabs( fValue - pValues[ i ] ) < fNearest )
1516 : {
1517 0 : fNearest = fabs( fValue - pValues[ i ] );
1518 0 : nNearest = i;
1519 : }
1520 : }
1521 0 : fValue = pValues[ nNearest ];
1522 : }
1523 : else
1524 : {
1525 0 : if( fValue < pValues[0] )
1526 0 : fValue = pValues[0];
1527 0 : if( fValue > pValues[1] )
1528 0 : fValue = pValues[1];
1529 : }
1530 0 : delete [] pValues;
1531 0 : mrSane.SetOptionValue( nOption, fValue, nElement );
1532 : #if OSL_DEBUG_LEVEL > 1
1533 : fprintf( stderr, "yields %lg\n", fValue );
1534 : #endif
1535 :
1536 :
1537 0 : return true;
1538 42 : }
1539 :
1540 :
1541 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|