1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
22 #include <tools/config.hxx>
23 #include <vcl/dibtools.hxx>
24 #include <vcl/layout.hxx>
25 #include <vcl/builderfactory.hxx>
26 #include <sanedlg.hxx>
29 #include <sal/macros.h>
30 #include <rtl/strbuf.hxx>
31 #include <boost/scoped_array.hpp>
32 #include "strings.hrc"
34 #define PREVIEW_WIDTH 113
35 #define PREVIEW_HEIGHT 160
37 #define RECT_SIZE_PIX 7
41 void DrawRectangles(vcl::RenderContext
& rRenderContext
, Point
& rUL
, Point
& rBR
)
43 int nMiddleX
, nMiddleY
;
46 aUR
= Point(rBR
.X(), rUL
.Y());
47 aBL
= Point(rUL
.X(), rBR
.Y());
48 nMiddleX
= (rBR
.X() - rUL
.X()) / 2 + rUL
.X();
49 nMiddleY
= (rBR
.Y() - rUL
.Y()) / 2 + rUL
.Y();
51 rRenderContext
.DrawLine(rUL
, aBL
);
52 rRenderContext
.DrawLine(aBL
, rBR
);
53 rRenderContext
.DrawLine(rBR
, aUR
);
54 rRenderContext
.DrawLine(aUR
, rUL
);
55 rRenderContext
.DrawRect(Rectangle(rUL
, Size(RECT_SIZE_PIX
,RECT_SIZE_PIX
)));
56 rRenderContext
.DrawRect(Rectangle(aBL
, Size(RECT_SIZE_PIX
, -RECT_SIZE_PIX
)));
57 rRenderContext
.DrawRect(Rectangle(rBR
, Size(-RECT_SIZE_PIX
, -RECT_SIZE_PIX
)));
58 rRenderContext
.DrawRect(Rectangle(aUR
, Size(-RECT_SIZE_PIX
, RECT_SIZE_PIX
)));
59 rRenderContext
.DrawRect(Rectangle(Point(nMiddleX
- RECT_SIZE_PIX
/ 2, rUL
.Y()), Size(RECT_SIZE_PIX
, RECT_SIZE_PIX
)));
60 rRenderContext
.DrawRect(Rectangle(Point(nMiddleX
- RECT_SIZE_PIX
/ 2, rBR
.Y()), Size(RECT_SIZE_PIX
, -RECT_SIZE_PIX
)));
61 rRenderContext
.DrawRect(Rectangle(Point(rUL
.X(), nMiddleY
- RECT_SIZE_PIX
/ 2), Size(RECT_SIZE_PIX
, RECT_SIZE_PIX
)));
62 rRenderContext
.DrawRect(Rectangle(Point(rBR
.X(), nMiddleY
- RECT_SIZE_PIX
/ 2), Size(-RECT_SIZE_PIX
, RECT_SIZE_PIX
)));
67 class ScanPreview
: public vcl::Window
70 enum DragDirection
{ TopLeft
, Top
, TopRight
, Right
, BottomRight
, Bottom
,
73 Bitmap maPreviewBitmap
;
74 Rectangle maPreviewRect
;
75 Point maTopLeft
, maBottomRight
;
76 Point maMinTopLeft
, maMaxBottomRight
;
77 VclPtr
<SaneDlg
> mpParentDialog
;
78 DragDirection meDragDirection
;
84 ScanPreview(vcl::Window
* pParent
, WinBits nStyle
)
85 : Window(pParent
, nStyle
)
86 , maMaxBottomRight(PREVIEW_WIDTH
, PREVIEW_HEIGHT
)
87 , mpParentDialog(NULL
)
88 , meDragDirection(TopLeft
)
95 virtual ~ScanPreview()
100 virtual void dispose() SAL_OVERRIDE
102 mpParentDialog
.clear();
103 vcl::Window::dispose();
106 void Init(SaneDlg
*pParent
)
108 mpParentDialog
= pParent
;
111 void ResetForNewScanner()
114 maBottomRight
= Point();
115 maMinTopLeft
= Point();
116 maMaxBottomRight
= Point(PREVIEW_WIDTH
, PREVIEW_HEIGHT
);
125 mbDragEnable
= false;
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;
139 void GetPreviewLogicRect(Point
& rTopLeft
, Point
&rBottomRight
) const
141 rTopLeft
= GetLogicPos(maTopLeft
);
142 rBottomRight
= GetLogicPos(maBottomRight
);
144 void GetMaxLogicRect(Point
& rTopLeft
, Point
&rBottomRight
) const
146 rTopLeft
= maMinTopLeft
;
147 rBottomRight
= maMaxBottomRight
;
150 void ChangePreviewLogicTopLeftY(long Y
)
153 aPoint
= GetPixelPos(aPoint
);
154 maTopLeft
.Y() = aPoint
.Y();
156 void ChangePreviewLogicTopLeftX(long X
)
159 aPoint
= GetPixelPos(aPoint
);
160 maTopLeft
.X() = aPoint
.X();
162 void ChangePreviewLogicBottomRightY(long Y
)
165 aPoint
= GetPixelPos(aPoint
);
166 maBottomRight
.Y() = aPoint
.Y();
168 void ChangePreviewLogicBottomRightX(long X
)
171 aPoint
= GetPixelPos(aPoint
);
172 maBottomRight
.X() = aPoint
.X();
174 void SetPreviewLogicRect(const Point
& rTopLeft
, const Point
&rBottomRight
)
176 maTopLeft
= GetPixelPos(rTopLeft
);
177 maBottomRight
= GetPixelPos(rBottomRight
);
178 maPreviewRect
= Rectangle(maTopLeft
,
179 Size(maBottomRight
.X() - maTopLeft
.X(),
180 maBottomRight
.Y() - maTopLeft
.Y()));
182 void SetPreviewMaxRect(const Point
& rTopLeft
, const Point
&rBottomRight
)
184 maMinTopLeft
= rTopLeft
;
185 maMaxBottomRight
= rBottomRight
;
187 void DrawDrag(vcl::RenderContext
& rRenderContext
);
188 void UpdatePreviewBounds();
189 void SetBitmap(SvStream
&rStream
)
191 ReadDIB(maPreviewBitmap
, rStream
, true);
193 virtual Size
GetOptimalSize() const SAL_OVERRIDE
195 Size
aSize(LogicToPixel(Size(PREVIEW_WIDTH
, PREVIEW_HEIGHT
), MAP_APPFONT
));
196 aSize
.setWidth(aSize
.getWidth()+1);
197 aSize
.setHeight(aSize
.getHeight()+1);
202 VCL_BUILDER_DECL_FACTORY(ScanPreview
)
204 WinBits nWinStyle
= 0;
205 OString sBorder
= VclBuilder::extractCustomProperty(rMap
);
206 if (!sBorder
.isEmpty())
207 nWinStyle
|= WB_BORDER
;
208 rRet
= VclPtr
<ScanPreview
>::Create(pParent
, nWinStyle
);
211 SaneDlg::SaneDlg( vcl::Window
* pParent
, Sane
& rSane
, bool bScanEnabled
) :
212 ModalDialog(pParent
, "SaneDialog", "modules/scanner/ui/sanedialog.ui"),
214 mbScanEnabled( bScanEnabled
),
222 get(mpOKButton
, "ok");
223 get(mpCancelButton
, "cancel");
224 get(mpDeviceInfoButton
, "deviceInfoButton");
225 get(mpPreviewButton
, "previewButton");
226 get(mpScanButton
, "scanButton");
227 get(mpButtonOption
, "optionsButton");
228 get(mpOptionTitle
, "optionTitleLabel");
229 Size
aSize(LogicToPixel(Size(130, 102), MAP_APPFONT
));
230 mpOptionTitle
->set_width_request(aSize
.Width());
231 mpOptionTitle
->set_height_request(aSize
.Height() / 2);
232 get(mpOptionDescTxt
, "optionsDescLabel");
233 get(mpVectorTxt
, "vectorLabel");
234 get(mpLeftField
, "leftSpinbutton");
235 get(mpTopField
, "topSpinbutton");
236 get(mpRightField
, "rightSpinbutton");
237 get(mpBottomField
, "bottomSpinbutton");
238 get(mpDeviceBox
, "deviceCombobox");
239 get(mpReslBox
, "reslCombobox");
240 get(mpAdvancedBox
, "advancedCheckbutton");
241 get(mpVectorBox
, "vectorSpinbutton-nospin");
242 get(mpQuantumRangeBox
, "quantumRangeCombobox");
243 get(mpStringRangeBox
, "stringRangeCombobox");
244 get(mpStringEdit
, "stringEntry");
245 get(mpNumericEdit
, "numericEntry");
246 get(mpOptionBox
, "optionSvTreeListBox");
247 mpOptionBox
->set_width_request(aSize
.Width());
248 mpOptionBox
->set_height_request(aSize
.Height());
249 get(mpBoolCheckBox
, "boolCheckbutton");
250 get(mpPreview
, "preview");
251 mpPreview
->Init(this);
254 InitDevices(); // opens first sane device
259 mpDeviceInfoButton
->SetClickHdl( LINK( this, SaneDlg
, ClickBtnHdl
) );
260 mpPreviewButton
->SetClickHdl( LINK( this, SaneDlg
, ClickBtnHdl
) );
261 mpScanButton
->SetClickHdl( LINK( this, SaneDlg
, ClickBtnHdl
) );
262 mpButtonOption
->SetClickHdl( LINK( this, SaneDlg
, ClickBtnHdl
) );
263 mpDeviceBox
->SetSelectHdl( LINK( this, SaneDlg
, SelectHdl
) );
264 mpOptionBox
->SetSelectHdl( LINK( this, SaneDlg
, OptionsBoxSelectHdl
) );
265 mpOKButton
->SetClickHdl( LINK( this, SaneDlg
, ClickBtnHdl
) );
266 mpCancelButton
->SetClickHdl( LINK( this, SaneDlg
, ClickBtnHdl
) );
267 mpBoolCheckBox
->SetClickHdl( LINK( this, SaneDlg
, ClickBtnHdl
) );
268 mpStringEdit
->SetModifyHdl( LINK( this, SaneDlg
, ModifyHdl
) );
269 mpNumericEdit
->SetModifyHdl( LINK( this, SaneDlg
, ModifyHdl
) );
270 mpVectorBox
->SetModifyHdl( LINK( this, SaneDlg
, ModifyHdl
) );
271 mpReslBox
->SetModifyHdl( LINK( this, SaneDlg
, ModifyHdl
) );
272 mpStringRangeBox
->SetSelectHdl( LINK( this, SaneDlg
, SelectHdl
) );
273 mpQuantumRangeBox
->SetSelectHdl( LINK( this, SaneDlg
, SelectHdl
) );
274 mpLeftField
->SetModifyHdl( LINK( this, SaneDlg
, ModifyHdl
) );
275 mpRightField
->SetModifyHdl( LINK( this, SaneDlg
, ModifyHdl
) );
276 mpTopField
->SetModifyHdl( LINK( this, SaneDlg
, ModifyHdl
) );
277 mpBottomField
->SetModifyHdl( LINK( this, SaneDlg
, ModifyHdl
) );
278 mpAdvancedBox
->SetClickHdl( LINK( this, SaneDlg
, ClickBtnHdl
) );
280 maOldLink
= mrSane
.SetReloadOptionsHdl( LINK( this, SaneDlg
, ReloadSaneOptionsHdl
) );
282 mpOptionBox
->SetNodeBitmaps(get
<FixedImage
>("plus")->GetImage(),
283 get
<FixedImage
>("minus")->GetImage());
284 mpOptionBox
->SetStyle(mpOptionBox
->GetStyle() |
285 WB_HASLINES
| WB_HASBUTTONS
| WB_NOINITIALSELECTION
|
286 WB_HASBUTTONSATROOT
| WB_HASLINESATROOT
);
294 void SaneDlg::dispose()
296 mrSane
.SetReloadOptionsHdl(maOldLink
);
298 mpCancelButton
.clear();
299 mpDeviceInfoButton
.clear();
300 mpPreviewButton
.clear();
301 mpScanButton
.clear();
302 mpButtonOption
.clear();
303 mpOptionTitle
.clear();
304 mpOptionDescTxt
.clear();
308 mpRightField
.clear();
309 mpBottomField
.clear();
312 mpAdvancedBox
.clear();
314 mpQuantumRangeBox
.clear();
315 mpStringRangeBox
.clear();
316 mpBoolCheckBox
.clear();
317 mpStringEdit
.clear();
318 mpNumericEdit
.clear();
321 ModalDialog::dispose();
326 ResId
SaneResId( sal_uInt32 nID
)
328 static ResMgr
* pResMgr
= ResMgr::CreateResMgr( "scn" );
329 return ResId( nID
, *pResMgr
);
334 short SaneDlg::Execute()
336 if( ! Sane::IsSane() )
338 ScopedVclPtrInstance
< MessageDialog
> aErrorBox(nullptr, SaneResId(STR_COULD_NOT_BE_INIT
));
339 aErrorBox
->Execute();
343 return ModalDialog::Execute();
346 void SaneDlg::InitDevices()
348 if( ! Sane::IsSane() )
351 if( mrSane
.IsOpen() )
353 mrSane
.ReloadDevices();
354 mpDeviceBox
->Clear();
355 for (int i
= 0; i
< Sane::CountDevices(); ++i
)
356 mpDeviceBox
->InsertEntry(Sane::GetName(i
));
357 if( Sane::CountDevices() )
360 mpDeviceBox
->SelectEntryPos(0);
364 void SaneDlg::InitFields()
366 if( ! Sane::IsSane() )
369 int nOption
, i
, nValue
;
371 bool bSuccess
= false;
372 const char *ppSpecialOptions
[] = {
381 mpPreview
->EnableDrag();
383 Point aTopLeft
, aBottomRight
;
384 mpPreview
->GetPreviewLogicRect(aTopLeft
, aBottomRight
);
385 Point aMinTopLeft
, aMaxBottomRight
;
386 mpPreview
->GetMaxLogicRect(aMinTopLeft
, aMaxBottomRight
);
387 mpScanButton
->Show( mbScanEnabled
);
389 if( ! mrSane
.IsOpen() )
393 nOption
= mrSane
.GetOptionByName( "resolution" );
398 bSuccess
= mrSane
.GetOptionValue( nOption
, fRes
);
401 mpReslBox
->Enable( true );
403 mpReslBox
->SetValue( (long)fRes
);
404 double *pDouble
= NULL
;
405 nValue
= mrSane
.GetRange( nOption
, pDouble
);
410 mpReslBox
->SetMin( (long)pDouble
[0] );
411 mpReslBox
->SetMax( (long)pDouble
[ nValue
-1 ] );
412 for( i
=0; i
<nValue
; i
++ )
414 if( i
== 0 || i
== nValue
-1 || ! ( ((int)pDouble
[i
]) % 20) )
415 mpReslBox
->InsertValue( (long)pDouble
[i
] );
420 mpReslBox
->SetMin( (long)pDouble
[0] );
421 mpReslBox
->SetMax( (long)pDouble
[1] );
422 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
426 // workaround: offer at least some more standard dpi resolution between
429 for ( int nRes
= (long) pDouble
[0] * 2; nRes
< (long) pDouble
[1]; nRes
= nRes
* 2 )
431 if ( !bGot300
&& nRes
> 300 ) {
432 nRes
= 300; bGot300
= 1;
434 mpReslBox
->InsertValue(nRes
);
436 mpReslBox
->InsertValue( (long)pDouble
[1] );
440 mpReslBox
->Enable( false );
445 mpReslBox
->Enable( false );
448 for( i
= 0; i
< 4; i
++ )
450 char const *pOptionName
= NULL
;
451 MetricField
* pField
= NULL
;
455 pOptionName
= "tl-x";
456 pField
= mpLeftField
;
459 pOptionName
= "tl-y";
463 pOptionName
= "br-x";
464 pField
= mpRightField
;
467 pOptionName
= "br-y";
468 pField
= mpBottomField
;
470 nOption
= pOptionName
? mrSane
.GetOptionByName( pOptionName
) : -1;
474 bSuccess
= mrSane
.GetOptionValue( nOption
, fValue
, 0 );
477 if( mrSane
.GetOptionUnit( nOption
) == SANE_UNIT_MM
)
479 pField
->SetUnit( FUNIT_MM
);
480 pField
->SetValue( (int)fValue
, FUNIT_MM
);
482 else // SANE_UNIT_PIXEL
484 pField
->SetValue( (int)fValue
, FUNIT_CUSTOM
);
485 pField
->SetCustomUnitText(OUString("Pixel"));
488 case 0: aTopLeft
.X() = (int)fValue
;break;
489 case 1: aTopLeft
.Y() = (int)fValue
;break;
490 case 2: aBottomRight
.X() = (int)fValue
;break;
491 case 3: aBottomRight
.Y() = (int)fValue
;break;
494 double *pDouble
= NULL
;
495 nValue
= mrSane
.GetRange( nOption
, pDouble
);
500 pField
->SetMin( (long)pDouble
[0] );
502 pField
->SetMax( (long)pDouble
[ nValue
-1 ] );
504 pField
->SetMax( (long)pDouble
[ 1 ] );
508 case 0: aMinTopLeft
.X() = pField
->GetMin();break;
509 case 1: aMinTopLeft
.Y() = pField
->GetMin();break;
510 case 2: aMaxBottomRight
.X() = pField
->GetMax();break;
511 case 3: aMaxBottomRight
.Y() = pField
->GetMax();break;
517 case 0: aMinTopLeft
.X() = (int)fValue
;break;
518 case 1: aMinTopLeft
.Y() = (int)fValue
;break;
519 case 2: aMaxBottomRight
.X() = (int)fValue
;break;
520 case 3: aMaxBottomRight
.Y() = (int)fValue
;break;
523 pField
->Enable( true );
527 mpPreview
->DisableDrag();
533 pField
->SetMax( PREVIEW_WIDTH
);
534 pField
->SetValue( 0 );
539 pField
->SetMax( PREVIEW_HEIGHT
);
540 pField
->SetValue( 0 );
543 aMaxBottomRight
.X() = PREVIEW_WIDTH
;
544 aBottomRight
.X() = PREVIEW_WIDTH
;
545 pField
->SetMax( PREVIEW_WIDTH
);
546 pField
->SetValue( PREVIEW_WIDTH
);
549 aMaxBottomRight
.Y() = PREVIEW_HEIGHT
;
550 aBottomRight
.Y() = PREVIEW_HEIGHT
;
551 pField
->SetMax( PREVIEW_HEIGHT
);
552 pField
->SetValue( PREVIEW_HEIGHT
);
555 pField
->Enable( false );
559 mpPreview
->SetPreviewMaxRect(aMinTopLeft
, aMaxBottomRight
);
560 mpPreview
->SetPreviewLogicRect(aTopLeft
, aBottomRight
);
561 mpPreview
->Invalidate();
564 mpOptionBox
->Clear();
565 SvTreeListEntry
* pParentEntry
= 0;
566 bool bGroupRejected
= false;
567 for( i
= 1; i
< mrSane
.CountOptions(); i
++ )
569 OUString aOption
=mrSane
.GetOptionName( i
);
570 bool bInsertAdvanced
=
571 (mrSane
.GetOptionCap( i
) & SANE_CAP_ADVANCED
) == 0 ||
572 mpAdvancedBox
->IsChecked();
573 if( mrSane
.GetOptionType( i
) == SANE_TYPE_GROUP
)
575 if( bInsertAdvanced
)
577 aOption
= mrSane
.GetOptionTitle( i
);
578 pParentEntry
= mpOptionBox
->InsertEntry( aOption
);
579 bGroupRejected
= false;
582 bGroupRejected
= true;
584 else if( !aOption
.isEmpty() &&
585 ! ( mrSane
.GetOptionCap( i
) &
587 SANE_CAP_HARD_SELECT
|
590 bInsertAdvanced
&& ! bGroupRejected
)
592 bool bIsSpecial
= false;
593 for( size_t n
= 0; !bIsSpecial
&&
594 n
< SAL_N_ELEMENTS(ppSpecialOptions
); n
++ )
596 if( aOption
== OUString::createFromAscii(ppSpecialOptions
[n
]) )
602 mpOptionBox
->InsertEntry( aOption
, pParentEntry
);
604 mpOptionBox
->InsertEntry( aOption
);
610 IMPL_LINK( SaneDlg
, ClickBtnHdl
, Button
*, pButton
)
612 if( mrSane
.IsOpen() )
614 if( pButton
== mpDeviceInfoButton
)
616 OUString
aString(SaneResId(STR_DEVICE_DESC
));
617 aString
= aString
.replaceFirst( "%s", Sane::GetName( mrSane
.GetDeviceNumber() ) );
618 aString
= aString
.replaceFirst( "%s", Sane::GetVendor( mrSane
.GetDeviceNumber() ) );
619 aString
= aString
.replaceFirst( "%s", Sane::GetModel( mrSane
.GetDeviceNumber() ) );
620 aString
= aString
.replaceFirst( "%s", Sane::GetType( mrSane
.GetDeviceNumber() ) );
621 ScopedVclPtrInstance
< MessageDialog
> aInfoBox(this, aString
, VCL_MESSAGE_INFO
);
624 else if( pButton
== mpPreviewButton
)
626 else if( pButton
== mpBoolCheckBox
)
628 mrSane
.SetOptionValue( mnCurrentOption
,
629 mpBoolCheckBox
->IsChecked() );
631 else if( pButton
== mpButtonOption
)
634 SANE_Value_Type nType
= mrSane
.GetOptionType( mnCurrentOption
);
637 case SANE_TYPE_BUTTON
:
638 mrSane
.ActivateButtonOption( mnCurrentOption
);
640 case SANE_TYPE_FIXED
:
643 int nElements
= mrSane
.GetOptionElements( mnCurrentOption
);
644 boost::scoped_array
<double> x(new double[ nElements
]);
645 boost::scoped_array
<double> y(new double[ nElements
]);
646 for( int i
= 0; i
< nElements
; i
++ )
648 mrSane
.GetOptionValue( mnCurrentOption
, y
.get() );
650 ScopedVclPtrInstance
< GridDialog
> aGrid( x
.get(), y
.get(), nElements
, this );
651 aGrid
->SetText( mrSane
.GetOptionName( mnCurrentOption
) );
652 aGrid
->setBoundings( 0, mfMin
, nElements
, mfMax
);
653 if( aGrid
->Execute() && aGrid
->getNewYValues() )
654 mrSane
.SetOptionValue( mnCurrentOption
, aGrid
->getNewYValues() );
658 case SANE_TYPE_STRING
:
659 case SANE_TYPE_GROUP
:
663 else if( pButton
== mpAdvancedBox
)
665 ReloadSaneOptionsHdl( NULL
);
668 if( pButton
== mpOKButton
|| pButton
== mpScanButton
)
670 double fRes
= (double)mpReslBox
->GetValue();
671 SetAdjustedNumericalValue( "resolution", fRes
);
672 UpdateScanArea(true);
674 EndDialog( mrSane
.IsOpen() ? 1 : 0 );
675 doScan
= (pButton
== mpScanButton
);
677 else if( pButton
== mpCancelButton
)
685 IMPL_LINK( SaneDlg
, SelectHdl
, ListBox
*, pListBox
)
687 if( pListBox
== mpDeviceBox
&& Sane::IsSane() && Sane::CountDevices() )
689 int nNewNumber
= mpDeviceBox
->GetSelectEntryPos();
690 int nOldNumber
= mrSane
.GetDeviceNumber();
691 if (nNewNumber
!= nOldNumber
)
694 mrSane
.Open(nNewNumber
);
695 mpPreview
->ResetForNewScanner();
699 if( mrSane
.IsOpen() )
701 if( pListBox
== mpQuantumRangeBox
)
703 OString
aValue(OUStringToOString(mpQuantumRangeBox
->GetSelectEntry(),
704 osl_getThreadTextEncoding()));
705 double fValue
= atof(aValue
.getStr());
706 mrSane
.SetOptionValue( mnCurrentOption
, fValue
, mnCurrentElement
);
708 else if( pListBox
== mpStringRangeBox
)
710 mrSane
.SetOptionValue( mnCurrentOption
, mpStringRangeBox
->GetSelectEntry() );
716 IMPL_LINK( SaneDlg
, OptionsBoxSelectHdl
, SvTreeListBox
*, pBox
)
718 if( pBox
== mpOptionBox
&& Sane::IsSane() )
721 mpOptionBox
->GetEntryText( mpOptionBox
->FirstSelected() );
722 int nOption
= mrSane
.GetOptionByName(OUStringToOString(aOption
,
723 osl_getThreadTextEncoding()).getStr());
724 if( nOption
!= -1 && nOption
!= mnCurrentOption
)
727 mnCurrentOption
= nOption
;
728 mpOptionTitle
->SetText( mrSane
.GetOptionTitle( mnCurrentOption
) );
729 SANE_Value_Type nType
= mrSane
.GetOptionType( mnCurrentOption
);
730 SANE_Constraint_Type nConstraint
;
733 case SANE_TYPE_BOOL
: EstablishBoolOption();break;
734 case SANE_TYPE_STRING
:
735 nConstraint
= mrSane
.GetOptionConstraintType( mnCurrentOption
);
736 if( nConstraint
== SANE_CONSTRAINT_STRING_LIST
)
737 EstablishStringRange();
739 EstablishStringOption();
741 case SANE_TYPE_FIXED
:
744 nConstraint
= mrSane
.GetOptionConstraintType( mnCurrentOption
);
745 int nElements
= mrSane
.GetOptionElements( mnCurrentOption
);
746 mnCurrentElement
= 0;
747 if( nConstraint
== SANE_CONSTRAINT_RANGE
||
748 nConstraint
== SANE_CONSTRAINT_WORD_LIST
)
749 EstablishQuantumRange();
753 EstablishNumericOption();
757 if( nElements
<= 10 )
759 mpVectorBox
->SetValue( 1 );
760 mpVectorBox
->SetMin( 1 );
762 mrSane
.GetOptionElements( mnCurrentOption
) );
763 mpVectorBox
->Show( true );
764 mpVectorTxt
->Show( true );
769 // bring up dialog only on button click
770 EstablishButtonOption();
775 case SANE_TYPE_BUTTON
:
776 EstablishButtonOption();
785 IMPL_LINK( SaneDlg
, ModifyHdl
, Edit
*, pEdit
)
787 if( mrSane
.IsOpen() )
789 if( pEdit
== mpStringEdit
)
791 mrSane
.SetOptionValue( mnCurrentOption
, mpStringEdit
->GetText() );
793 else if( pEdit
== mpReslBox
)
795 double fRes
= (double)mpReslBox
->GetValue();
796 int nOption
= mrSane
.GetOptionByName( "resolution" );
799 double* pDouble
= NULL
;
800 int nValues
= mrSane
.GetRange( nOption
, pDouble
);
804 for( i
= 0; i
< nValues
; i
++ )
806 if( fRes
== pDouble
[i
] )
812 else if( nValues
== 0 )
814 if( fRes
< pDouble
[ 0 ] )
816 if( fRes
> pDouble
[ 1 ] )
820 mpReslBox
->SetValue( (sal_uLong
)fRes
);
823 else if( pEdit
== mpNumericEdit
)
826 OString
aContents(OUStringToOString(mpNumericEdit
->GetText(),
827 osl_getThreadTextEncoding()));
828 fValue
= atof(aContents
.getStr());
829 if( mfMin
!= mfMax
&& ( fValue
< mfMin
|| fValue
> mfMax
) )
834 else if( fValue
> mfMax
)
836 sprintf( pBuf
, "%g", fValue
);
837 mpNumericEdit
->SetText( OUString( pBuf
, strlen(pBuf
), osl_getThreadTextEncoding() ) );
839 mrSane
.SetOptionValue( mnCurrentOption
, fValue
, mnCurrentElement
);
841 else if( pEdit
== mpVectorBox
)
843 mnCurrentElement
= mpVectorBox
->GetValue()-1;
845 if( mrSane
.GetOptionValue( mnCurrentOption
, fValue
, mnCurrentElement
))
848 sprintf( pBuf
, "%g", fValue
);
849 OUString
aValue( pBuf
, strlen(pBuf
), osl_getThreadTextEncoding() );
850 mpNumericEdit
->SetText( aValue
);
851 mpQuantumRangeBox
->SelectEntry( aValue
);
854 else if( pEdit
== mpTopField
)
856 mpPreview
->ChangePreviewLogicTopLeftY(mpTopField
->GetValue());
857 mpPreview
->Invalidate();
859 else if( pEdit
== mpLeftField
)
861 mpPreview
->ChangePreviewLogicTopLeftX(mpLeftField
->GetValue());
862 mpPreview
->Invalidate();
864 else if( pEdit
== mpBottomField
)
866 mpPreview
->ChangePreviewLogicBottomRightY(mpBottomField
->GetValue());
867 mpPreview
->Invalidate();
869 else if( pEdit
== mpRightField
)
871 mpPreview
->ChangePreviewLogicBottomRightX(mpRightField
->GetValue());
872 mpPreview
->Invalidate();
878 IMPL_LINK( SaneDlg
, ReloadSaneOptionsHdl
, Sane
*, /*pSane*/ )
880 mnCurrentOption
= -1;
881 mnCurrentElement
= 0;
884 mpPreview
->Invalidate();
888 void SaneDlg::AcquirePreview()
890 if( ! mrSane
.IsOpen() )
893 UpdateScanArea( true );
894 // set small resolution for preview
895 double fResl
= (double)mpReslBox
->GetValue();
896 SetAdjustedNumericalValue( "resolution", 30.0 );
898 int nOption
= mrSane
.GetOptionByName( "preview" );
901 OUString
aString(SaneResId(STR_SLOW_PREVIEW
));
902 ScopedVclPtrInstance
< MessageDialog
> aBox(this, aString
, VCL_MESSAGE_WARNING
, VCL_BUTTONS_OK_CANCEL
);
903 if (aBox
->Execute() == RET_CANCEL
)
907 mrSane
.SetOptionValue( nOption
, true );
909 BitmapTransporter aTransporter
;
910 if( ! mrSane
.Start( aTransporter
) )
912 ScopedVclPtrInstance
< MessageDialog
> aErrorBox(this, SaneResId(STR_ERROR_SCAN
));
913 aErrorBox
->Execute();
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() );
921 aTransporter
.getStream().Seek( STREAM_SEEK_TO_BEGIN
);
922 mpPreview
->SetBitmap(aTransporter
.getStream());
925 SetAdjustedNumericalValue( "resolution", fResl
);
926 mpReslBox
->SetValue( (sal_uLong
)fResl
);
928 mpPreview
->UpdatePreviewBounds();
929 mpPreview
->Invalidate();
932 void ScanPreview::UpdatePreviewBounds()
936 maPreviewRect
= Rectangle( maTopLeft
,
937 Size( maBottomRight
.X() - maTopLeft
.X(),
938 maBottomRight
.Y() - maTopLeft
.Y() )
943 Size
aBMSize( maPreviewBitmap
.GetSizePixel() );
944 if( aBMSize
.Width() > aBMSize
.Height() && aBMSize
.Width() )
946 int nVHeight
= (maBottomRight
.X() - maTopLeft
.X()) * aBMSize
.Height() / aBMSize
.Width();
947 maPreviewRect
= Rectangle( Point( maTopLeft
.X(), ( maTopLeft
.Y() + maBottomRight
.Y() )/2 - nVHeight
/2 ),
948 Size( maBottomRight
.X() - maTopLeft
.X(),
951 else if (aBMSize
.Height())
953 int nVWidth
= (maBottomRight
.Y() - maTopLeft
.Y()) * aBMSize
.Width() / aBMSize
.Height();
954 maPreviewRect
= Rectangle( Point( ( maTopLeft
.X() + maBottomRight
.X() )/2 - nVWidth
/2, maTopLeft
.Y() ),
956 maBottomRight
.Y() - maTopLeft
.Y() ) );
961 void ScanPreview::Paint(vcl::RenderContext
& rRenderContext
, const Rectangle
& rRect
)
963 Window::Paint(rRenderContext
, rRect
);
964 rRenderContext
.SetMapMode(MAP_APPFONT
);
965 rRenderContext
.SetFillColor(Color(COL_WHITE
));
966 rRenderContext
.SetLineColor(Color(COL_WHITE
));
967 rRenderContext
.DrawRect(Rectangle(Point(0, 0),
968 Size(PREVIEW_WIDTH
, PREVIEW_HEIGHT
)));
969 rRenderContext
.SetMapMode(MapMode(MAP_PIXEL
));
970 // check for sane values
971 rRenderContext
.DrawBitmap(maPreviewRect
.TopLeft(), maPreviewRect
.GetSize(), maPreviewBitmap
);
974 DrawDrag(rRenderContext
);
977 void SaneDlg::DisableOption()
979 mpBoolCheckBox
->Show( false );
980 mpStringEdit
->Show( false );
981 mpNumericEdit
->Show( false );
982 mpQuantumRangeBox
->Show( false );
983 mpStringRangeBox
->Show( false );
984 mpButtonOption
->Show( false );
985 mpVectorBox
->Show( false );
986 mpVectorTxt
->Show( false );
987 mpOptionDescTxt
->Show( false );
990 void SaneDlg::EstablishBoolOption()
992 bool bSuccess
, bValue
;
994 bSuccess
= mrSane
.GetOptionValue( mnCurrentOption
, bValue
);
997 mpBoolCheckBox
->SetText( mrSane
.GetOptionName( mnCurrentOption
) );
998 mpBoolCheckBox
->Check( bValue
);
999 mpBoolCheckBox
->Show( true );
1003 void SaneDlg::EstablishStringOption()
1008 bSuccess
= mrSane
.GetOptionValue( mnCurrentOption
, aValue
);
1011 mpOptionDescTxt
->SetText( mrSane
.GetOptionName( mnCurrentOption
) );
1012 mpOptionDescTxt
->Show( true );
1013 mpStringEdit
->SetText(OStringToOUString(aValue
, osl_getThreadTextEncoding()));
1014 mpStringEdit
->Show( true );
1018 void SaneDlg::EstablishStringRange()
1020 const char** ppStrings
= mrSane
.GetStringConstraint( mnCurrentOption
);
1021 mpStringRangeBox
->Clear();
1022 for( int i
= 0; ppStrings
[i
] != 0; i
++ )
1023 mpStringRangeBox
->InsertEntry( OUString( ppStrings
[i
], strlen(ppStrings
[i
]), osl_getThreadTextEncoding() ) );
1025 mrSane
.GetOptionValue( mnCurrentOption
, aValue
);
1026 mpStringRangeBox
->SelectEntry(OStringToOUString(aValue
, osl_getThreadTextEncoding()));
1027 mpStringRangeBox
->Show( true );
1028 mpOptionDescTxt
->SetText( mrSane
.GetOptionName( mnCurrentOption
) );
1029 mpOptionDescTxt
->Show( true );
1032 void SaneDlg::EstablishQuantumRange()
1039 int nValues
= mrSane
.GetRange( mnCurrentOption
, mpRange
);
1042 mfMin
= mpRange
[ 0 ];
1043 mfMax
= mpRange
[ 1 ];
1046 EstablishNumericOption();
1048 else if( nValues
> 0 )
1051 mpQuantumRangeBox
->Clear();
1052 mfMin
= mpRange
[ 0 ];
1053 mfMax
= mpRange
[ nValues
-1 ];
1054 for( int i
= 0; i
< nValues
; i
++ )
1056 sprintf( pBuf
, "%g", mpRange
[ i
] );
1057 mpQuantumRangeBox
->InsertEntry( OUString( pBuf
, strlen(pBuf
), osl_getThreadTextEncoding() ) );
1060 if( mrSane
.GetOptionValue( mnCurrentOption
, fValue
, mnCurrentElement
) )
1062 sprintf( pBuf
, "%g", fValue
);
1063 mpQuantumRangeBox
->SelectEntry( OUString( pBuf
, strlen(pBuf
), osl_getThreadTextEncoding() ) );
1065 mpQuantumRangeBox
->Show( true );
1066 OUString
aText( mrSane
.GetOptionName( mnCurrentOption
) );
1068 aText
+= mrSane
.GetOptionUnitName( mnCurrentOption
);
1069 mpOptionDescTxt
->SetText( aText
);
1070 mpOptionDescTxt
->Show( true );
1074 void SaneDlg::EstablishNumericOption()
1079 bSuccess
= mrSane
.GetOptionValue( mnCurrentOption
, fValue
);
1084 OUString
aText( mrSane
.GetOptionName( mnCurrentOption
) );
1086 aText
+= mrSane
.GetOptionUnitName( mnCurrentOption
);
1087 if( mfMin
!= mfMax
)
1089 sprintf( pBuf
, " < %g ; %g >", mfMin
, mfMax
);
1090 aText
+= OUString( pBuf
, strlen(pBuf
), osl_getThreadTextEncoding() );
1092 mpOptionDescTxt
->SetText( aText
);
1093 mpOptionDescTxt
->Show( true );
1094 sprintf( pBuf
, "%g", fValue
);
1095 mpNumericEdit
->SetText( OUString( pBuf
, strlen(pBuf
), osl_getThreadTextEncoding() ) );
1096 mpNumericEdit
->Show( true );
1099 void SaneDlg::EstablishButtonOption()
1101 mpOptionDescTxt
->SetText( mrSane
.GetOptionName( mnCurrentOption
) );
1102 mpOptionDescTxt
->Show( true );
1103 mpButtonOption
->Show( true );
1106 void ScanPreview::MouseMove(const MouseEvent
& rMEvt
)
1110 Point aMousePos
= rMEvt
.GetPosPixel();
1111 // move into valid area
1112 Point aLogicPos
= GetLogicPos( aMousePos
);
1113 aMousePos
= GetPixelPos( aLogicPos
);
1114 switch( meDragDirection
)
1116 case TopLeft
: maTopLeft
= aMousePos
; break;
1117 case Top
: maTopLeft
.Y() = aMousePos
.Y(); break;
1119 maTopLeft
.Y() = aMousePos
.Y();
1120 maBottomRight
.X() = aMousePos
.X();
1122 case Right
: maBottomRight
.X() = aMousePos
.X(); break;
1123 case BottomRight
: maBottomRight
= aMousePos
; break;
1124 case Bottom
: maBottomRight
.Y() = aMousePos
.Y(); break;
1126 maTopLeft
.X() = aMousePos
.X();
1127 maBottomRight
.Y() = aMousePos
.Y();
1129 case Left
: maTopLeft
.X() = aMousePos
.X(); break;
1133 if( maTopLeft
.X() > maBottomRight
.X() )
1135 nSwap
= maTopLeft
.X();
1136 maTopLeft
.X() = maBottomRight
.X();
1137 maBottomRight
.X() = nSwap
;
1139 if( maTopLeft
.Y() > maBottomRight
.Y() )
1141 nSwap
= maTopLeft
.Y();
1142 maTopLeft
.Y() = maBottomRight
.Y();
1143 maBottomRight
.Y() = nSwap
;
1146 mpParentDialog
->UpdateScanArea(false);
1148 Window::MouseMove( rMEvt
);
1151 void ScanPreview::MouseButtonDown( const MouseEvent
& rMEvt
)
1153 Point aMousePixel
= rMEvt
.GetPosPixel();
1155 if( ! mbIsDragging
&& mbDragEnable
)
1157 int nMiddleX
= ( maBottomRight
.X() - maTopLeft
.X() ) / 2 - RECT_SIZE_PIX
/2 + maTopLeft
.X();
1158 int nMiddleY
= ( maBottomRight
.Y() - maTopLeft
.Y() ) / 2 - RECT_SIZE_PIX
/2 + maTopLeft
.Y();
1159 if( aMousePixel
.Y() >= maTopLeft
.Y() &&
1160 aMousePixel
.Y() < maTopLeft
.Y() + RECT_SIZE_PIX
)
1162 if( aMousePixel
.X() >= maTopLeft
.X() &&
1163 aMousePixel
.X() < maTopLeft
.X() + RECT_SIZE_PIX
)
1165 meDragDirection
= TopLeft
;
1166 aMousePixel
= maTopLeft
;
1167 mbIsDragging
= true;
1169 else if( aMousePixel
.X() >= nMiddleX
&&
1170 aMousePixel
.X() < nMiddleX
+ RECT_SIZE_PIX
)
1172 meDragDirection
= Top
;
1173 aMousePixel
.Y() = maTopLeft
.Y();
1174 mbIsDragging
= true;
1176 else if( aMousePixel
.X() > maBottomRight
.X() - RECT_SIZE_PIX
&&
1177 aMousePixel
.X() <= maBottomRight
.X() )
1179 meDragDirection
= TopRight
;
1180 aMousePixel
= Point( maBottomRight
.X(), maTopLeft
.Y() );
1181 mbIsDragging
= true;
1184 else if( aMousePixel
.Y() >= nMiddleY
&&
1185 aMousePixel
.Y() < nMiddleY
+ RECT_SIZE_PIX
)
1187 if( aMousePixel
.X() >= maTopLeft
.X() &&
1188 aMousePixel
.X() < maTopLeft
.X() + RECT_SIZE_PIX
)
1190 meDragDirection
= Left
;
1191 aMousePixel
.X() = maTopLeft
.X();
1192 mbIsDragging
= true;
1194 else if( aMousePixel
.X() > maBottomRight
.X() - RECT_SIZE_PIX
&&
1195 aMousePixel
.X() <= maBottomRight
.X() )
1197 meDragDirection
= Right
;
1198 aMousePixel
.X() = maBottomRight
.X();
1199 mbIsDragging
= true;
1202 else if( aMousePixel
.Y() <= maBottomRight
.Y() &&
1203 aMousePixel
.Y() > maBottomRight
.Y() - RECT_SIZE_PIX
)
1205 if( aMousePixel
.X() >= maTopLeft
.X() &&
1206 aMousePixel
.X() < maTopLeft
.X() + RECT_SIZE_PIX
)
1208 meDragDirection
= BottomLeft
;
1209 aMousePixel
= Point( maTopLeft
.X(), maBottomRight
.Y() );
1210 mbIsDragging
= true;
1212 else if( aMousePixel
.X() >= nMiddleX
&&
1213 aMousePixel
.X() < nMiddleX
+ RECT_SIZE_PIX
)
1215 meDragDirection
= Bottom
;
1216 aMousePixel
.Y() = maBottomRight
.Y();
1217 mbIsDragging
= true;
1219 else if( aMousePixel
.X() > maBottomRight
.X() - RECT_SIZE_PIX
&&
1220 aMousePixel
.X() <= maBottomRight
.X() )
1222 meDragDirection
= BottomRight
;
1223 aMousePixel
= maBottomRight
;
1224 mbIsDragging
= true;
1230 SetPointerPosPixel( aMousePixel
);
1233 Window::MouseButtonDown( rMEvt
);
1236 void ScanPreview::MouseButtonUp( const MouseEvent
& rMEvt
)
1240 mpParentDialog
->UpdateScanArea(true);
1242 mbIsDragging
= false;
1244 Window::MouseButtonUp( rMEvt
);
1247 void ScanPreview::DrawDrag(vcl::RenderContext
& rRenderContext
)
1249 static Point aLastUL
, aLastBR
;
1254 RasterOp eROP
= rRenderContext
.GetRasterOp();
1255 rRenderContext
.SetRasterOp(ROP_INVERT
);
1256 rRenderContext
.SetMapMode(MapMode(MAP_PIXEL
));
1259 DrawRectangles(rRenderContext
, aLastUL
, aLastBR
);
1261 aLastUL
= maTopLeft
;
1262 aLastBR
= maBottomRight
;
1263 DrawRectangles(rRenderContext
, maTopLeft
, maBottomRight
);
1266 rRenderContext
.SetRasterOp(eROP
);
1267 rRenderContext
.SetMapMode(MAP_APPFONT
);
1270 Point
ScanPreview::GetPixelPos( const Point
& rIn
) const
1273 ( ( rIn
.X() * PREVIEW_WIDTH
) /
1274 ( maMaxBottomRight
.X() - maMinTopLeft
.X() ) )
1276 ( ( rIn
.Y() * PREVIEW_HEIGHT
)
1277 / ( maMaxBottomRight
.Y() - maMinTopLeft
.Y() ) )
1280 return LogicToPixel(aConvert
, MAP_APPFONT
);
1283 Point
ScanPreview::GetLogicPos(const Point
& rIn
) const
1285 Point aConvert
= PixelToLogic(rIn
, MAP_APPFONT
);
1286 if( aConvert
.X() < 0 )
1288 if( aConvert
.X() >= PREVIEW_WIDTH
)
1289 aConvert
.X() = PREVIEW_WIDTH
-1;
1290 if( aConvert
.Y() < 0 )
1292 if( aConvert
.Y() >= PREVIEW_HEIGHT
)
1293 aConvert
.Y() = PREVIEW_HEIGHT
-1;
1295 aConvert
.X() *= ( maMaxBottomRight
.X() - maMinTopLeft
.X() );
1296 aConvert
.X() /= PREVIEW_WIDTH
;
1297 aConvert
.Y() *= ( maMaxBottomRight
.Y() - maMinTopLeft
.Y() );
1298 aConvert
.Y() /= PREVIEW_HEIGHT
;
1302 void SaneDlg::UpdateScanArea(bool bSend
)
1304 if (!mpPreview
->IsDragEnabled())
1308 mpPreview
->GetPreviewLogicRect(aUL
, aBR
);
1310 mpLeftField
->SetValue( aUL
.X() );
1311 mpTopField
->SetValue( aUL
.Y() );
1312 mpRightField
->SetValue( aBR
.X() );
1313 mpBottomField
->SetValue( aBR
.Y() );
1318 if( mrSane
.IsOpen() )
1320 SetAdjustedNumericalValue( "tl-x", (double)aUL
.X() );
1321 SetAdjustedNumericalValue( "tl-y", (double)aUL
.Y() );
1322 SetAdjustedNumericalValue( "br-x", (double)aBR
.X() );
1323 SetAdjustedNumericalValue( "br-y", (double)aBR
.Y() );
1327 bool SaneDlg::LoadState()
1331 if( ! Sane::IsSane() )
1334 const char* pEnv
= getenv("HOME");
1335 OUString aFileName
= pEnv
? OUString(pEnv
, strlen(pEnv
), osl_getThreadTextEncoding() ) : OUString();
1336 aFileName
+= "/.so_sane_state";
1337 Config
aConfig( aFileName
);
1338 if( ! aConfig
.HasGroup( "SANE" ) )
1341 aConfig
.SetGroup( "SANE" );
1342 OString aString
= aConfig
.ReadKey( "SO_LastSaneDevice" );
1343 for( i
= 0; i
< Sane::CountDevices() && !aString
.equals(OUStringToOString(Sane::GetName(i
), osl_getThreadTextEncoding())); i
++ ) ;
1344 if( i
== Sane::CountDevices() )
1348 mrSane
.Open( aString
.getStr() );
1353 if( mrSane
.IsOpen() )
1355 int iMax
= aConfig
.GetKeyCount();
1356 for (i
= 0; i
< iMax
; ++i
)
1358 aString
= aConfig
.GetKeyName( i
);
1359 OString aValue
= aConfig
.ReadKey( i
);
1360 int nOption
= mrSane
.GetOptionByName( aString
.getStr() );
1364 if (aValue
.startsWith("BOOL="))
1366 aValue
= aValue
.copy(RTL_CONSTASCII_LENGTH("BOOL="));
1367 bool aBOOL
= aValue
.toInt32() != 0;
1368 mrSane
.SetOptionValue( nOption
, aBOOL
);
1370 else if (aValue
.startsWith("STRING="))
1372 aValue
= aValue
.copy(RTL_CONSTASCII_LENGTH("STRING="));
1373 mrSane
.SetOptionValue(nOption
,OStringToOUString(aValue
, osl_getThreadTextEncoding()) );
1375 else if (aValue
.startsWith("NUMERIC="))
1377 aValue
= aValue
.copy(RTL_CONSTASCII_LENGTH("NUMERIC="));
1379 sal_Int32 nIndex
= 0;
1383 OString aSub
= aValue
.getToken(0, ':', nIndex
);
1385 sscanf(aSub
.getStr(), "%lg", &fValue
);
1386 SetAdjustedNumericalValue(aString
.getStr(), fValue
, n
++);
1388 while ( nIndex
>= 0 );
1399 void SaneDlg::SaveState()
1401 if( ! Sane::IsSane() )
1404 const char* pEnv
= getenv( "HOME" );
1408 aFileName
= OUString::createFromAscii(pEnv
) + "/.so_sane_state";
1410 aFileName
= OStringToOUString("", osl_getThreadTextEncoding()) + "/.so_sane_state";
1412 Config
aConfig( aFileName
);
1413 aConfig
.DeleteGroup( "SANE" );
1414 aConfig
.SetGroup( "SANE" );
1415 aConfig
.WriteKey( "SO_LastSANEDevice",
1416 OUStringToOString(mpDeviceBox
->GetSelectEntry(), RTL_TEXTENCODING_UTF8
) );
1418 static char const* pSaveOptions
[] = {
1425 for( size_t i
= 0; i
< SAL_N_ELEMENTS(pSaveOptions
); ++i
)
1427 OString aOption
= pSaveOptions
[i
];
1428 int nOption
= mrSane
.GetOptionByName( pSaveOptions
[i
] );
1431 SANE_Value_Type nType
= mrSane
.GetOptionType( nOption
);
1434 case SANE_TYPE_BOOL
:
1437 if( mrSane
.GetOptionValue( nOption
, bValue
) )
1439 OStringBuffer
aString("BOOL=");
1440 aString
.append(static_cast<sal_Int32
>(bValue
));
1441 aConfig
.WriteKey(aOption
, aString
.makeStringAndClear());
1445 case SANE_TYPE_STRING
:
1448 if( mrSane
.GetOptionValue( nOption
, aValue
) )
1450 OStringBuffer
aString("STRING=");
1451 aString
.append(aValue
);
1452 aConfig
.WriteKey( aOption
, aString
.makeStringAndClear() );
1456 case SANE_TYPE_FIXED
:
1459 OStringBuffer
aString("NUMERIC=");
1464 for( n
= 0; n
< mrSane
.GetOptionElements( nOption
); n
++ )
1466 if( ! mrSane
.GetOptionValue( nOption
, fValue
, n
) )
1469 aString
.append(':');
1470 sprintf( buf
, "%lg", fValue
);
1471 aString
.append(buf
);
1473 if( n
>= mrSane
.GetOptionElements( nOption
) )
1474 aConfig
.WriteKey( aOption
, aString
.makeStringAndClear() );
1484 bool SaneDlg::SetAdjustedNumericalValue(
1485 const char* pOption
,
1490 if( ! Sane::IsSane() || ! mrSane
.IsOpen() || ( nOption
= mrSane
.GetOptionByName( pOption
) ) == -1 )
1493 if( nElement
< 0 || nElement
>= mrSane
.GetOptionElements( nOption
) )
1496 double* pValues
= NULL
;
1498 if( ( nValues
= mrSane
.GetRange( nOption
, pValues
) ) < 0 )
1504 #if OSL_DEBUG_LEVEL > 1
1505 fprintf( stderr
, "SaneDlg::SetAdjustedNumericalValue( \"%s\", %lg ) ",
1512 double fNearest
= 1e6
;
1513 for( int i
= 0; i
< nValues
; i
++ )
1515 if( fabs( fValue
- pValues
[ i
] ) < fNearest
)
1517 fNearest
= fabs( fValue
- pValues
[ i
] );
1521 fValue
= pValues
[ nNearest
];
1525 if( fValue
< pValues
[0] )
1526 fValue
= pValues
[0];
1527 if( fValue
> pValues
[1] )
1528 fValue
= pValues
[1];
1531 mrSane
.SetOptionValue( nOption
, fValue
, nElement
);
1532 #if OSL_DEBUG_LEVEL > 1
1533 fprintf( stderr
, "yields %lg\n", fValue
);
1541 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */