kpresenter

KPrBackground.cpp
1/* This file is part of the KDE project
2 Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
3 Copyright (C) 2004-2006 Thorsten Zachmann <zachmann@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19*/
20
21#include "KPrBackground.h"
22#include "KPrDocument.h"
23#include <tdeapplication.h>
24#include "KPrGradientCollection.h"
25#include "KPrTextObject.h"
26#include "KPrPage.h"
27#include "KPrUtils.h"
28#include "KPrBrush.h"
29
30#include <tqpainter.h>
31#include <tqpicture.h>
32#include <tqfileinfo.h>
33
34#include <KoRichText.h>
35#include <KoTextObject.h>
36// for getenv ()
37#include <stdlib.h>
38using namespace std;
39#include <kdebug.h>
40#include <tdeglobalsettings.h>
41#include <KoStore.h>
42#include <KoStoreDevice.h>
43#include <KoGenStyles.h>
44#include <KoXmlNS.h>
45
46KPrBackGround::KPrBackGround( KPrPage *_page )
47 // : footerHeight( 0 )
48{
49 backType = BT_COLOR;
50 backView = BV_CENTER;
51 backColor1 = TQt::white;
52 backColor2 = TQt::white;
53 bcType = BCT_PLAIN;
54 unbalanced = false;
55 xfactor = 100;
56 yfactor = 100;
57
58 gradientPixmap = 0L;
59 m_page=_page;
60}
61
62void KPrBackGround::setBackPicture( const KoPicture& picture )
63{
64 if ( backType != BT_PICTURE )
65 return;
66 backPicture = pictureCollection()->insertPicture(picture);
67}
68
69void KPrBackGround::setBackPicture ( const KoPictureKey& key )
70{
71 if ( backType != BT_PICTURE )
72 return;
73 backPicture = pictureCollection()->findOrLoad(key.filename(), key.lastModified() );
74}
75
76void KPrBackGround::drawBackground( TQPainter *_painter, const KoTextZoomHandler* zoomHandler,
77 const TQRect& _crect, bool _drawBorders )
78{
79 TQRect pageRect = zoomHandler->zoomRect( m_page->getPageRect() );
80 TQRect crect = pageRect.intersect( _crect );
81 if ( crect.isEmpty() )
82 return;
83 TQSize ext = pageRect.size();
84 drawBackground( _painter, ext, crect, _drawBorders );
85}
86
87void KPrBackGround::drawBackground( TQPainter *_painter, const TQSize& ext, const TQRect& crect, bool _drawBorders )
88{
89 if ( m_page->displayBackground() )
90 {
91 _painter->save();
92 switch ( backType )
93 {
94 case BT_COLOR:
95 drawBackColor( _painter, ext, crect );
96 break;
97 case BT_CLIPART:
98 case BT_PICTURE:
99 {
100 if ( backView == BV_CENTER )
101 drawBackColor( _painter, ext, crect );
102 drawBackPix( _painter, ext, crect );
103 break;
104 }
105 default:
106 break;
107 }
108
109 if ( _drawBorders )
110 drawBorders( _painter, ext, crect );
111
112 _painter->restore();
113 }
114}
115
116void KPrBackGround::reload()
117{
118 if ( backType == BT_PICTURE || backType == BT_CLIPART )
119 backPicture = pictureCollection()->insertPicture(backPicture);
120 else
121 backPicture.clear();
122}
123
124
125TQDomElement KPrBackGround::save( TQDomDocument &doc )
126{
127 TQString tag = m_page->masterPage() == 0 ? "MASTERPAGE" : "PAGE";
128 TQDomElement page=doc.createElement( tag );
129 TQDomElement element;
130
131 element=doc.createElement("BACKMASTER");
132 element.setAttribute( "useMasterBackground", static_cast<int>(m_page->useMasterBackground() ) );
133 element.setAttribute( "displayMasterPageObject", static_cast<int>( m_page->displayObjectFromMasterPage() ));
134 element.setAttribute( "displayBackground", static_cast<int>( m_page->displayBackground() ));
135 page.appendChild(element);
136 if ( !m_page->useMasterBackground() )
137 {
138
139 if (backType!=BT_COLOR) {
140 element=doc.createElement("BACKTYPE");
141 element.setAttribute("value", static_cast<int>( backType ));
142 page.appendChild(element);
143 }
144
145 if (backView!=BV_CENTER) {
146 element=doc.createElement("BACKVIEW");
147 element.setAttribute("value", static_cast<int>( backView ));
148 page.appendChild(element);
149 }
150
151 if (backColor1!=TQt::white) {
152 element=doc.createElement("BACKCOLOR1");
153 element.setAttribute("color", backColor1.name());
154 page.appendChild(element);
155 }
156
157 if (backColor2!=TQt::white) {
158 element=doc.createElement("BACKCOLOR2");
159 element.setAttribute("color", backColor2.name());
160 page.appendChild(element);
161 }
162
163 if (bcType!=BCT_PLAIN) {
164 element=doc.createElement("BCTYPE");
165 element.setAttribute("value", static_cast<int>( bcType ));
166 page.appendChild(element);
167 }
168
169 if (xfactor!=100 || yfactor!=100 || unbalanced) {
170 element=doc.createElement("BGRADIENT");
171 element.setAttribute("unbalanced", static_cast<int>( unbalanced ));
172 element.setAttribute("xfactor", xfactor);
173 element.setAttribute("yfactor", yfactor);
174 page.appendChild(element);
175 }
176
177 if ( !backPicture.isNull() && ( ( backType == BT_PICTURE ) || ( backType == BT_CLIPART ) ) )
178 {
179 element = doc.createElement( "BACKPICTUREKEY" );
180
181 backPicture.getKey().saveAttributes( element );
182 page.appendChild( element );
183 }
184 }
185
186 return page;
187}
188
189
190void KPrBackGround::saveOasisBackgroundPageStyle( KoGenStyle& stylepageauto, KoGenStyles& mainStyles )
191{
192 switch ( backType )
193 {
194 case BT_COLOR:
195 {
196 TQBrush qbrush( backColor1 );
197 KPrBrush brush( qbrush, backColor1, backColor2, bcType,
198 bcType == BCT_PLAIN ? FT_BRUSH : FT_GRADIENT,
199 unbalanced, xfactor, yfactor );
200 brush.saveOasisFillStyle( stylepageauto, mainStyles );
201 } break;
202 case BT_BRUSH:
203 case BT_CLIPART:
204 case BT_PICTURE:
205 {
206 stylepageauto.addProperty("draw:fill", "bitmap" );
207 stylepageauto.addProperty("draw:fill-image-name", saveOasisPictureStyle( mainStyles ) );
208 TQString repeat = "repeat";
209 switch ( backView )
210 {
211 case BV_ZOOM:
212 repeat = "stretch";
213 break;
214 case BV_CENTER:
215 repeat = "no-repeat";
216 break;
217 case BV_TILED:
218 repeat = "repeat";
219 break;
220 }
221 stylepageauto.addProperty( "style:repeat", repeat );
222 } break;
223 }
224}
225
226
227TQString KPrBackGround::saveOasisPictureStyle( KoGenStyles& mainStyles )
228{
229 //<draw:fill-image draw:name="Pattern" xlink:href="Pictures/100000000000005E0000005E43C87AF2.png" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad"/>
230 KoGenStyle pictureStyle( KPrDocument::STYLE_PICTURE /*no family name*/ );
231 pictureStyle.addAttribute( "xlink:show", "embed" );
232 pictureStyle.addAttribute( "xlink:actuate", "onLoad" );
233 pictureStyle.addAttribute( "xlink:type", "simple" );
234 pictureStyle.addAttribute( "xlink:href", pictureCollection()->getOasisFileName(backPicture ) );
235 return mainStyles.lookup( pictureStyle, "picture" );
236}
237
238
239void KPrBackGround::loadOasis(KoOasisContext & context )
240{
241 KoStyleStack& styleStack = context.styleStack();
242 kdDebug()<<"KPrBackGround::loadOasis()\n";
243 styleStack.setTypeProperties( "drawing-page" );
244 if ( styleStack.hasAttributeNS( KoXmlNS::draw, "fill" ) )
245 {
246 const TQString fill = styleStack.attributeNS( KoXmlNS::draw, "fill" );
247 kdDebug(33001) <<"fill page type :" << fill << endl;
248 if ( fill == "solid" || fill == "gradient" )
249 {
250 KPrBrush brush;
251 brush.loadOasisFillStyle( context, "drawing-page" );
252 if ( brush.getFillType() == FT_BRUSH )
253 {
254 setBackColor1( brush.getBrush().color() );
255 setBackColorType( BCT_PLAIN );
256 }
257 else
258 {
259 setBackColor1( brush.getGColor1() );
260 setBackColor2( brush.getGColor2() );
261 setBackColorType( brush.getGType() );
262 setBackUnbalanced( brush.getGUnbalanced() );
263 setBackXFactor( brush.getGXFactor() );
264 setBackYFactor( brush.getGYFactor() );
265 }
266 setBackType( BT_COLOR );
267 }
268 else if ( fill == "bitmap" )
269 {
270 TQString style = styleStack.attributeNS( KoXmlNS::draw, "fill-image-name" );
271 TQDomElement* draw =context.oasisStyles().drawStyles()[style];
272
273 const TQString href( draw->attributeNS( KoXmlNS::xlink, "href", TQString()) );
274 kdDebug()<<" href: "<<href<<endl;
275 if ( !href.isEmpty() )
276 {
277 TQString strExtension;
278 const int result=href.findRev(".");
279 if (result>=0)
280 {
281 strExtension=href.mid(result+1); // As we are using KoPicture, the extension should be without the dot.
282 }
283 TQString filename(href);
284 const KoPictureKey key(filename, TQDateTime::currentDateTime(TQt::UTC));
285 backPicture.setKey(key);
286
287 KoStore* store = context.store();
288 if ( store->open( filename ) )
289 {
290 KoStoreDevice dev(store);
291 if ( !backPicture.load( &dev, strExtension ) )
292 kdWarning() << "Cannot load picture: " << filename << " " << href << endl;
293 store->close();
294 }
295 pictureCollection()->insertPicture( key, backPicture );
296 }
297
298 if ( styleStack.hasAttributeNS( KoXmlNS::style, "repeat" ) )
299 {
300 TQString repeat = styleStack.attributeNS( KoXmlNS::style, "repeat" );
301 if ( repeat == "stretch" )
302 setBackView( BV_ZOOM );
303 else if ( repeat == "no-repeat" )
304 setBackView( BV_CENTER );
305 else
306 setBackView( BV_TILED );
307 }
308 else
309 setBackView( BV_TILED );; // use tiled as default
310
311 setBackType(BT_PICTURE);
312 }
313 }
314}
315
316void KPrBackGround::load( const TQDomElement &element )
317{
318 //compatible with old file format kpresenter-1.4
319 TQDomElement e=element.namedItem("BACKMASTER").toElement();
320 if ( !e.isNull() )
321 {
322 if ( e.hasAttribute( "useMasterBackground" ) )
323 {
324 m_page->setUseMasterBackground( (bool)e.attribute("useMasterBackground").toInt());
325 }
326 else //for kpresenter-1.4
327 m_page->setUseMasterBackground( true );
328
329 if(e.hasAttribute("displayMasterPageObject"))
330 {
331 m_page->setDisplayObjectFromMasterPage( (bool)e.attribute("displayMasterPageObject").toInt());
332 }
333 if(e.hasAttribute("displayBackground"))
334 {
335 m_page->setDisplayBackground( (bool)e.attribute("displayBackground").toInt());
336 }
337 }
338 else
339 m_page->setUseMasterBackground( false );
340
341 e=element.namedItem("BACKTYPE").toElement();
342 if(!e.isNull()) {
343 int tmp=0;
344 if(e.hasAttribute("value"))
345 tmp=e.attribute("value").toInt();
346 setBackType(static_cast<BackType>(tmp));
347 }
348 e=element.namedItem("BACKVIEW").toElement();
349 if(!e.isNull()) {
350 int tmp=0;
351 if(e.hasAttribute("value"))
352 tmp=e.attribute("value").toInt();
353 setBackView(static_cast<BackView>(tmp));
354 }
355 e=element.namedItem("BACKCOLOR1").toElement();
356 if(!e.isNull()) {
357 int red=0, green=0, blue=0;
358 if(e.hasAttribute("red"))
359 red=e.attribute("red").toInt();
360 if(e.hasAttribute("green"))
361 green=e.attribute("green").toInt();
362 if(e.hasAttribute("blue"))
363 blue=e.attribute("blue").toInt();
364 if(e.hasAttribute("color"))
365 setBackColor1(TQColor(e.attribute("color")));
366 else
367 setBackColor1(TQColor(red, green, blue));
368 }
369 e=element.namedItem("BACKCOLOR2").toElement();
370 if(!e.isNull()) {
371 int red=0, green=0, blue=0;
372 if(e.hasAttribute("red"))
373 red=e.attribute("red").toInt();
374 if(e.hasAttribute("green"))
375 green=e.attribute("green").toInt();
376 if(e.hasAttribute("blue"))
377 blue=e.attribute("blue").toInt();
378 if(e.hasAttribute("color"))
379 setBackColor2(TQColor(e.attribute("color")));
380 else
381 setBackColor2(TQColor(red, green, blue));
382 }
383 e=element.namedItem("BGRADIENT").toElement();
384 if(!e.isNull()) {
385 int xf=0, yf=0, unbalanced=0;
386 if(e.hasAttribute("xfactor"))
387 xf=e.attribute("xfactor").toInt();
388 setBackXFactor(xf);
389 if(e.hasAttribute("yfactor"))
390 yf=e.attribute("yfactor").toInt();
391 setBackYFactor(yf);
392 if(e.hasAttribute("unbalanced"))
393 unbalanced=e.attribute("unbalanced").toInt();
394 setBackUnbalanced(static_cast<bool>(unbalanced));
395 }
396 e=element.namedItem("BCTYPE").toElement();
397 if(!e.isNull()) {
398 int tmp=0;
399 if(e.hasAttribute("value"))
400 tmp=e.attribute("value").toInt();
401 setBackColorType(static_cast<BCType>(tmp));
402 }
403 e=element.namedItem("BACKPICTUREKEY").toElement();
404 if(!e.isNull()) {
405 KoPictureKey key;
406 key.loadAttributes( e );
407 backPicture.clear();
408 backPicture.setKey( key );
409 // Image will be set by reload(), called by completeLoading()
410 }
411 e=element.namedItem("BACKPIXKEY").toElement();
412 if(!e.isNull()) {
413 KoPictureKey key;
414 key.loadAttributes( e );
415 backPicture.clear();
416 backPicture.setKey( key );
417 // Image will be set by reload(), called by completeLoading()
418 }
419 else {
420 // try to find a BACKPIX tag if the BACKPIXKEY is not available...
421 KoPictureKey key;
422 e=element.namedItem("BACKPIX").toElement();
423 if(!e.isNull()) {
424 bool openPic = true;
425 TQString _data;
426 TQString _fileName;
427 if(e.hasAttribute("data"))
428 _data=e.attribute("data");
429 if ( _data.isEmpty() )
430 openPic = true;
431 else
432 openPic = false;
433 if(e.hasAttribute("filename"))
434 _fileName=e.attribute("filename");
435 if ( !_fileName.isEmpty() )
436 {
437 if ( int _envVarB = _fileName.find( '$' ) >= 0 )
438 {
439 int _envVarE = _fileName.find( '/', _envVarB );
440 TQString path = getenv( TQFile::encodeName(_fileName.mid( _envVarB, _envVarE-_envVarB )) );
441 _fileName.replace( _envVarB-1, _envVarE-_envVarB+1, path );
442 }
443 }
444 if ( openPic )
445 // !! this loads it from the disk (unless it's in the image collection already)
446 backPicture = pictureCollection()->loadPicture( _fileName );
447 else
448 {
449 KoPictureKey key( _fileName );
450 backPicture.clear();
451 backPicture.setKey(key);
452 TQByteArray rawData=_data.utf8(); // XPM is normally ASCII, therefore UTF-8
453 rawData[rawData.size()-1]=char(10); // Replace the NULL character by a LINE FEED
454 TQBuffer buffer(rawData);
455 backPicture.loadXpm(&buffer);
456 }
457
458#if 0
459 if ( ext == orig_size.toTQSize() )
460 ext = backPicture.size();
461
462 backPicture = backPicture.scale( ext );
463#endif
464 }
465 }
466 e=element.namedItem("BACKCLIPKEY").toElement();
467 if(!e.isNull()) {
468 KoPictureKey clipKey;
469 clipKey.loadAttributes( e );
470 backPicture.clear();
471 backPicture.setKey(clipKey);
472 // Picture will be set by reload(), called by completeLoading()
473 }
474 else {
475 // try to find a BACKCLIP tag if the BACKCLIPKEY is not available...
476 e=element.namedItem("BACKCLIP").toElement();
477 if(!e.isNull()) {
478 TQString _fileName;
479 if(e.hasAttribute("filename"))
480 _fileName=e.attribute("filename");
481 if ( !_fileName.isEmpty() )
482 {
483 if ( int _envVarB = _fileName.find( '$' ) >= 0 )
484 {
485 int _envVarE = _fileName.find( '/', _envVarB );
486 TQString path = getenv( TQFile::encodeName(_fileName.mid( _envVarB, _envVarE-_envVarB )) );
487 _fileName.replace( _envVarB-1, _envVarE-_envVarB+1, path );
488 }
489 }
490 //KPClipartKey clipKey( _fileName, TQDateTime( pictureCollection()->tmpDate(),
491 // pictureCollection()->tmpTime() ) );
492 backPicture = pictureCollection()->loadPicture( _fileName ); // load from disk !
493 }
494 }
495}
496
497void KPrBackGround::drawBackColor( TQPainter *_painter, const TQSize& ext, const TQRect& crect )
498{
499 if ( (backType == BT_COLOR && bcType == BCT_PLAIN) || backColor1 == backColor2 ) //plain color
500 {
501 //kdDebug(33001) << "KPrBackGround::drawBackColor (filling " << DEBUGRECT(crect) << ")" << endl;
502 _painter->fillRect( crect, TQBrush( getBackColor1() ) );
503 }
504 else if (backType == BT_COLOR && bcType != BCT_PLAIN) { //gradient
505 if ( !gradientPixmap || gradientPixmap->size() != ext )
506 generateGradient( ext );
507 _painter->drawPixmap( crect.topLeft(), *gradientPixmap, crect );
508 }
509 else /*if ( backType == BT_CLIPART || backType == BT_PICTURE )*/ //no gradient or bg color
510 _painter->fillRect( crect, TQBrush( TQt::white ) );
511 return;
512}
513
514void KPrBackGround::drawBackPix( TQPainter *_painter, const TQSize& ext, const TQRect& /*crect*/ )
515{
516 /*kdDebug(33001) << "KPrBackGround::drawBackPix ext=" << ext.width() << "," << ext.height() << endl;
517 kdDebug(33001) << "mode=" << (backView==BV_ZOOM?"ZOOM":backView==BV_TILED?"TILED":backView==BV_CENTER?"CENTER":"OTHER")
518 << " crect=" << DEBUGRECT(crect) << endl;*/
519 if ( !backPicture.isNull() )
520 {
521 // depend on page size and desktop size
522 const TQSize _origSize = backPicture.getOriginalSize();
523 // NOTE: make all multiplications before any division
524 double w = _origSize.width();
525 w *= ext.width();
526#if KDE_IS_VERSION(3,1,90)
527 TQRect desk = TDEGlobalSettings::desktopGeometry(kapp->activeWindow());
528#else
529 TQRect desk = TQApplication::desktop()->screenGeometry();
530#endif
531 w /= desk.width();
532 double h = _origSize.height();
533 h *= ext.height();
534 h /= desk.height();
535 const TQSize _pixSize = TQSize( (int)w, (int)h );
536 TQPixmap backPix;
537
538 switch ( backView )
539 {
540 case BV_ZOOM:
541 backPix=backPicture.generatePixmap( ext, true );
542 _painter->drawPixmap( TQRect( 0, 0, ext.width(), ext.height() ), backPix );
543 break;
544 case BV_TILED:
545 backPix=backPicture.generatePixmap( _pixSize, true );
546 _painter->drawTiledPixmap( 0, 0, ext.width(), ext.height(), backPix );
547 break;
548 case BV_CENTER:
549 {
550 backPix=backPicture.generatePixmap( _pixSize, true );
551
552 TQPixmap *pix = new TQPixmap( ext.width(), ext.height() );
553 bool delPix = true;
554 int _x = 0, _y = 0;
555
556 if ( backPix.width() > pix->width() && backPix.height() > pix->height() )
557 bitBlt( pix, 0, 0, &backPix, backPix.width() - pix->width(), backPix.height() - pix->height(),
558 pix->width(), pix->height() );
559 else if ( backPix.width() > pix->width() )
560 {
561 bitBlt( pix, 0, 0, &backPix, backPix.width() - pix->width(), 0,
562 pix->width(), backPix.height() );
563 _y = ( pix->height() - backPix.height() ) / 2;
564 }
565 else if ( backPix.height() > pix->height() )
566 {
567 bitBlt( pix, 0, 0, &backPix, 0, backPix.height() - pix->height(),
568 backPix.width(), pix->height() );
569 _x = ( pix->width() - backPix.width() ) / 2;
570 }
571 else
572 {
573 _x = ( pix->width() - backPix.width() ) / 2;
574 _y = ( pix->height() - backPix.height() ) / 2;
575 delPix = false;
576 delete pix;
577 pix = &backPix;
578 }
579
580 if ( pix && !pix->isNull() )
581 _painter->drawPixmap( _x, _y, *pix );
582 if ( delPix ) delete pix;
583 }
584 break;
585 }
586 }
587}
588
589void KPrBackGround::drawBorders( TQPainter *_painter, const TQSize& /*ext*/, const TQRect& /*crect*/ )
590{
591 _painter->setPen( TQApplication::palette().active().color( TQColorGroup::Dark ) );
592 _painter->setBrush( TQt::NoBrush );
593
594 TQRect rect = m_page->getZoomPageRect();
595
596 _painter->drawRect( rect.x()-1,rect.y()-1,rect.width()+1,rect.height()+1 );
597}
598
599void KPrBackGround::generateGradient( const TQSize& size )
600{
601 if ( backType == BT_COLOR || backType == BT_CLIPART ||
602 backType == BT_PICTURE && backView == BV_CENTER ) {
603 removeGradient();
604 gradientPixmap = &gradientCollection()->getGradient( backColor1, backColor2, bcType, size,
605 unbalanced, xfactor, yfactor );
606 }
607
608 // Avoid keeping an unused gradient around
609 if ( (backType == BT_PICTURE || backType==BT_CLIPART) && gradientPixmap )
610 removeGradient();
611}
612
613void KPrBackGround::removeGradient()
614{
615 if ( gradientPixmap ) {
616 gradientCollection()->removeRef( backColor1, backColor2, bcType, gradientPixmap->size(),
617 unbalanced, xfactor, yfactor);
618 gradientPixmap = 0;
619 }
620}
621
622KoPictureCollection * KPrBackGround::pictureCollection() const
623{
624 return m_page->kPresenterDoc()->pictureCollection();
625}
626
627KPrGradientCollection * KPrBackGround::gradientCollection() const
628{
629 return m_page->kPresenterDoc()->gradientCollection();
630}
631
632void KPrBackGround::setBackGround( const struct Settings &settings )
633{
634 backType = settings.m_backType;
635 backColor1 = settings.m_backColor1;
636 backColor2 = settings.m_backColor2;
637 bcType = settings.m_bcType;
638 unbalanced = settings.m_unbalanced;
639 xfactor = settings.m_xfactor;
640 yfactor = settings.m_yfactor;
641 removeGradient();
642 setBackPicture( settings.m_backPictureKey );
643 backView = settings.m_backView;
644
645}
646
647struct KPrBackGround::Settings KPrBackGround::getBackGround() const
648{
649 return Settings( backType, backColor1, backColor2,
650 bcType, unbalanced, xfactor, yfactor,
651 backPicture.getKey(), backView);
652}
Class: KPrGradientCollection Holds a collection of gradients, and is able to provide a gradient for a...