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