javauis/lcdui_akn/lcdui/src/Cmidformrow.cpp
branchRCL_3
changeset 19 04becd199f91
child 60 6c158198356e
equal deleted inserted replaced
16:f5050f1da672 19:04becd199f91
       
     1 /*
       
     2 * Copyright (c) 2003-2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Implements the Form LCDUI component.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // For LyaoutMirrored() method.
       
    20 #include <AknUtils.h>
       
    21 
       
    22 #include "CMIDFormRow.h"
       
    23 // CMIDForm API for iForm
       
    24 #include "CMIDForm.h"
       
    25 // API for items on rows
       
    26 #include "CMIDControlItem.h"
       
    27 #include "CMIDItemLabel.h"
       
    28 
       
    29 
       
    30 CMIDFormRow* CMIDFormRow::NewL(CMIDForm& aForm)
       
    31 {
       
    32     CMIDFormRow* self = new(ELeave) CMIDFormRow(aForm);
       
    33     CleanupStack::PushL(self);
       
    34     self->ActivateL();
       
    35     CleanupStack::Pop(self);
       
    36     return self;
       
    37 }
       
    38 
       
    39 CMIDFormRow::~CMIDFormRow()
       
    40 {
       
    41     TInt i;
       
    42     for (i=0; i < iItems.Count(); i++)
       
    43     {
       
    44         if (CMIDForm::IsLabelContainerItem(*(iItems[i])))
       
    45         {
       
    46             delete iItems[i];
       
    47         }
       
    48         else if (CMIDForm::IsSpacerUsedForFormatting(*(iItems[i])))
       
    49         {
       
    50             delete iItems[i];
       
    51         }
       
    52     }
       
    53     iItems.Reset();
       
    54     iItems.Close();
       
    55 }
       
    56 
       
    57 TInt CMIDFormRow::CountComponentControls() const
       
    58 {
       
    59     return iItems.Count();
       
    60 }
       
    61 
       
    62 CCoeControl* CMIDFormRow::ComponentControl(TInt aIndex) const
       
    63 {
       
    64     return iItems[aIndex];
       
    65 }
       
    66 
       
    67 void CMIDFormRow::SizeChanged()
       
    68 {
       
    69     TInt xOff = 0;
       
    70 
       
    71     TSize size(0,0);
       
    72 
       
    73     TInt i;
       
    74     for (i=0; i < iItems.Count(); i++)
       
    75     {
       
    76         CMIDControlItem& ci = *(iItems[i]);
       
    77         size.iWidth += ci.Size().iWidth;
       
    78         if (ci.Size().iHeight > size.iHeight)
       
    79         {
       
    80             size.iHeight = ci.Size().iHeight;
       
    81         }
       
    82     }
       
    83 
       
    84     if (iAlignment == MMIDItem::ERight)
       
    85     {
       
    86         xOff = iForm.Width() - size.iWidth;
       
    87         // If it is mirrored layout, we need translate a row.
       
    88         if (AknLayoutUtils::LayoutMirrored())
       
    89         {
       
    90             xOff -= iForm.GetMidpNaviPos();
       
    91         }
       
    92     }
       
    93 
       
    94     if (iAlignment == MMIDItem::ECenter)
       
    95     {
       
    96         xOff = (iForm.Width() - size.iWidth) / 2;
       
    97     }
       
    98 
       
    99     for (i=0; i < iItems.Count(); i++)
       
   100     {
       
   101         CMIDControlItem& ci = *(iItems[i]);
       
   102         TInt yOff = 0;
       
   103         if (CMIDForm::LayoutBottom(ci))
       
   104         {
       
   105             yOff = size.iHeight - ci.Size().iHeight;
       
   106         }
       
   107         if (CMIDForm::LayoutVerticalCenter(ci))
       
   108         {
       
   109             yOff = (size.iHeight - ci.Size().iHeight) / 2;
       
   110         }
       
   111 
       
   112         // Form left margin is added in the beginning of each row
       
   113         TPoint newPosition = Position() + TPoint(xOff, yOff);
       
   114         TSize itemSize = ci.Size();
       
   115         TRect itemRect = TRect(newPosition, itemSize);
       
   116         ci.SetRect(itemRect);
       
   117         xOff += ci.Size().iWidth;
       
   118     }
       
   119 }
       
   120 
       
   121 TSize CMIDFormRow::MinimumSize()
       
   122 {
       
   123     if (iItems.Count() == 0)
       
   124     {
       
   125         return iEmptyRowSize;
       
   126     }
       
   127 
       
   128     TInt width = 0;
       
   129     TInt height = 0;
       
   130 
       
   131     for (TInt i=0; i < iItems.Count(); i++)
       
   132     {
       
   133         CMIDControlItem& ci = *(iItems[i]);
       
   134 
       
   135         width += CMIDForm::LayoutShrink(ci) ? ci.MinimumSize().iWidth : ci.PreferredSize().iWidth;
       
   136 
       
   137         if (CMIDForm::LayoutVerticalShrink(ci))
       
   138         {
       
   139             if (height < ci.MinimumSize().iHeight)
       
   140             {
       
   141                 height = ci.MinimumSize().iHeight;
       
   142             }
       
   143         }
       
   144         else
       
   145         {
       
   146             if (height < ci.PreferredSize().iHeight)
       
   147             {
       
   148                 height = ci.PreferredSize().iHeight;
       
   149             }
       
   150         }
       
   151     }
       
   152     return TSize(width, height);
       
   153 }
       
   154 
       
   155 void CMIDFormRow::AppendL(CMIDControlItem* aItem)
       
   156 {
       
   157     if (iForm.InitialAlignment() == MMIDItem::ELeft)
       
   158     {
       
   159         User::LeaveIfError(iItems.Append(aItem));
       
   160     }
       
   161     else
       
   162     {
       
   163         User::LeaveIfError(iItems.Insert(aItem, 0));
       
   164     }
       
   165     iCurrentWidth += aItem->Size().iWidth;
       
   166 }
       
   167 
       
   168 void CMIDFormRow::SetAlignment(MMIDItem::TLayout aAlignment)
       
   169 {
       
   170     ASSERT((aAlignment == MMIDItem::ELeft) || (aAlignment == MMIDItem::ERight) || (aAlignment == MMIDItem::ECenter));
       
   171     iAlignment = aAlignment;
       
   172 }
       
   173 
       
   174 /** */
       
   175 void CMIDFormRow::SizeItemsL()
       
   176 {
       
   177     TSize minSize = MinimumSize();
       
   178 
       
   179     // size the widths first
       
   180     TInt availableWidth = iForm.Width() - minSize.iWidth;
       
   181     // equation is also allowed - resizing when extra space is same as allowed
       
   182     if (availableWidth >= 0)
       
   183     {
       
   184         TInt totalExtraWidth = 0;
       
   185         for (TInt j=0; j < iItems.Count(); j++)
       
   186         {
       
   187             CMIDControlItem& ci = *(iItems[j]);
       
   188             if (CMIDForm::LayoutShrink(ci))
       
   189             {
       
   190                 totalExtraWidth += ci.PreferredSize().iWidth - ci.MinimumSize().iWidth;
       
   191             }
       
   192         }
       
   193 
       
   194         if (availableWidth > totalExtraWidth)
       
   195         {
       
   196             // just give all items what they want
       
   197             for (TInt j=0; j < iItems.Count(); j++)
       
   198             {
       
   199                 CMIDControlItem& ci = *(iItems[j]);
       
   200                 ci.SetSizeQuiet(ci.PreferredSize());
       
   201             }
       
   202 
       
   203             availableWidth -= totalExtraWidth;
       
   204         }
       
   205         else
       
   206         {
       
   207             // distribute the size
       
   208             TReal scaleFactor;
       
   209             if (availableWidth == totalExtraWidth)
       
   210             {
       
   211                 scaleFactor = 1;
       
   212             }
       
   213             else
       
   214             {
       
   215                 if (totalExtraWidth != 0)
       
   216                 {
       
   217                     scaleFactor = TReal(availableWidth) / TReal(totalExtraWidth);
       
   218                 }
       
   219                 else
       
   220                 {
       
   221                     scaleFactor = 1;
       
   222                 }
       
   223             }
       
   224 
       
   225             for (TInt j=0; j < iItems.Count(); j++)
       
   226             {
       
   227                 CMIDControlItem& ci = *(iItems[j]);
       
   228 
       
   229                 if (CMIDForm::LayoutShrink(ci))
       
   230                 {
       
   231                     TInt minAndPreferredDif = ci.PreferredSize().iWidth - ci.MinimumSize().iWidth;
       
   232                     TInt newMinAndPreferredDif = TInt(scaleFactor * TReal(minAndPreferredDif));
       
   233                     TInt newWidth = ci.MinimumSize().iWidth + Min(newMinAndPreferredDif, minAndPreferredDif);
       
   234                     availableWidth -= Min(newMinAndPreferredDif, minAndPreferredDif);
       
   235                     ci.SetSizeQuiet(TSize(newWidth, ci.Size().iHeight));
       
   236                 }
       
   237                 else
       
   238                 {
       
   239                     ci.SetSizeQuiet(TSize(ci.PreferredSize().iWidth, ci.Size().iHeight));
       
   240                 }
       
   241             }
       
   242         }
       
   243         // note: should probably do another pass through to make sure the above step
       
   244         // went ok and didn't suffer from rounding errors (ie that the Shrink items didn't
       
   245         // end up smaller than their preferred size (if we have size left over)
       
   246 
       
   247         // loop through and expand the items with Expand layout
       
   248         if (availableWidth > 0)
       
   249         {
       
   250             TInt numExpand = 0;
       
   251             // count the items with Expand layout
       
   252             for (TInt j=0; j < iItems.Count(); j++)
       
   253             {
       
   254                 CMIDControlItem& ci = *(iItems[j]);
       
   255 
       
   256                 if (CMIDForm::LayoutExpand(ci))
       
   257                 {
       
   258                     numExpand++;
       
   259                 }
       
   260             }
       
   261             if (numExpand > 0)
       
   262             {
       
   263                 TInt addedSize = availableWidth / numExpand;
       
   264                 TInt expandIdx = -1;
       
   265 
       
   266                 for (TInt j=0; j < iItems.Count(); j++)
       
   267                 {
       
   268                     CMIDControlItem& ci = *(iItems[j]);
       
   269 
       
   270                     if (CMIDForm::LayoutExpand(ci))
       
   271                     {
       
   272                         ci.SetSizeQuiet(ci.Size() + TSize(addedSize, 0));
       
   273                         availableWidth -= addedSize;
       
   274                         expandIdx = j;
       
   275                         // at the end of the loop this will hold the last expanded
       
   276                         // item. At that time we can check if we still have extra
       
   277                         // space remaining and give it to the item at this index
       
   278                     }
       
   279                 }
       
   280                 if (availableWidth > 0)
       
   281                 {
       
   282                     // if we still have extra width due to rounding error just give it to the last item
       
   283                     iItems[expandIdx]->SetSizeQuiet(iItems[expandIdx]->Size() + TSize(availableWidth, 0));
       
   284                 }
       
   285             }
       
   286         }
       
   287     }
       
   288 
       
   289 
       
   290     // the widths have been calculated. This could have changed the height
       
   291     // due to for example label wrapping so ask the control to check
       
   292     // the new width.
       
   293     TInt j;
       
   294     for (j=0; j < iItems.Count(); j++)
       
   295     {
       
   296         CMIDControlItem& ci = *(iItems[j]);
       
   297         ci.AdjustToNewWidthL(ci.Size().iWidth);
       
   298     }
       
   299 
       
   300     // now size the heights
       
   301 
       
   302     // first find the row height
       
   303     TInt rowHeight = 0;
       
   304     for (j=0; j < iItems.Count(); j++)
       
   305     {
       
   306         CMIDControlItem& ci = *(iItems[j]);
       
   307 
       
   308         TInt height = ci.PreferredSize().iHeight;
       
   309         if (CMIDForm::LayoutVerticalShrink(ci))
       
   310         {
       
   311             height = ci.MinimumSize().iHeight;
       
   312         }
       
   313         if (height > rowHeight)
       
   314         {
       
   315             rowHeight = height;
       
   316         }
       
   317     }
       
   318 
       
   319     if (iItems.Count() == 0)
       
   320     {//if not items use empty row height
       
   321         rowHeight = iEmptyRowSize.iHeight;
       
   322     }
       
   323 
       
   324     // now set the row heights
       
   325     for (j=0; j < iItems.Count(); j++)
       
   326     {
       
   327         CMIDControlItem& ci = *(iItems[j]);
       
   328 
       
   329         // first set the size normally, then change it based on shrink and expand directives
       
   330         ci.SetSizeQuiet(TSize(ci.Size().iWidth, ci.PreferredSize().iHeight));
       
   331         if (CMIDForm::LayoutVerticalShrink(ci))
       
   332         {
       
   333             TInt height = Min(ci.PreferredSize().iHeight, rowHeight);
       
   334             ci.SetSizeQuiet(TSize(ci.Size().iWidth, height));
       
   335         }
       
   336         if (CMIDForm::LayoutVerticalExpand(ci))
       
   337         {
       
   338             ci.SetSizeQuiet(TSize(ci.Size().iWidth, rowHeight));
       
   339         }
       
   340 
       
   341         ci.AdjustToSizeL(ci.Size());
       
   342     }
       
   343 
       
   344     // set the size of the row
       
   345     SetSize(TSize(iForm.Width(), rowHeight));
       
   346 }
       
   347 
       
   348 TInt CMIDFormRow::NumItems()
       
   349 {
       
   350     return iItems.Count();
       
   351 }
       
   352 
       
   353 TInt CMIDFormRow::Find(const CMIDControlItem* aItem) const
       
   354 {
       
   355     for (TInt i=0; i < iItems.Count(); i++)
       
   356     {
       
   357         if (aItem == iItems[i])
       
   358         {
       
   359             return i;
       
   360         }
       
   361     }
       
   362 
       
   363     return KErrNotFound;
       
   364 }
       
   365 
       
   366 CMIDControlItem* CMIDFormRow::Item(TInt aIndex)
       
   367 {
       
   368     ASSERT(aIndex >= 0 && aIndex < iItems.Count());
       
   369     return iItems[aIndex];
       
   370 }
       
   371 
       
   372 TBool CMIDFormRow::HasFocusableItemOnOrAboveScreen()
       
   373 {
       
   374     for (TInt i=0; i < iItems.Count(); i++)
       
   375     {
       
   376         if (iItems[i]->IsSelectable())
       
   377         {
       
   378             TRect rect = iItems[i]->Rect();
       
   379             if (rect.iTl.iY < iForm.Height())
       
   380             {
       
   381                 return ETrue;
       
   382             }
       
   383         }
       
   384     }
       
   385     return EFalse;
       
   386 }
       
   387 
       
   388 TBool CMIDFormRow::HasFocusableItemOnOrBelowScreen()
       
   389 {
       
   390     for (TInt i=0; i < iItems.Count(); i++)
       
   391     {
       
   392         if (iItems[i]->IsSelectable())
       
   393         {
       
   394             TRect rect = iItems[i]->Rect();
       
   395             if (rect.iBr.iY >= 0)
       
   396             {
       
   397                 return ETrue;
       
   398             }
       
   399         }
       
   400     }
       
   401     return EFalse;
       
   402 }
       
   403 
       
   404 CMIDControlItem* CMIDFormRow::FirstFocusableItemOnScreen()
       
   405 {
       
   406     TInt idx = -1;
       
   407     while (++idx < iItems.Count())
       
   408     {
       
   409         if (iItems[idx]->IsSelectable())
       
   410         {
       
   411             TRect rect = iItems[idx]->Rect();
       
   412             if (iForm.RectPartiallyVisible(rect))
       
   413             {
       
   414                 return iItems[idx];
       
   415             }
       
   416         }
       
   417     }
       
   418     return NULL;
       
   419 }
       
   420 
       
   421 CMIDControlItem* CMIDFormRow::FirstFocusableItem()
       
   422 {
       
   423     TInt idx = -1;
       
   424     while (++idx < iItems.Count())
       
   425     {
       
   426         if (iItems[idx]->IsSelectable())
       
   427         {
       
   428             return iItems[idx];
       
   429         }
       
   430     }
       
   431     return NULL;
       
   432 }
       
   433 
       
   434 CMIDControlItem* CMIDFormRow::LastFocusableItem()
       
   435 {
       
   436     TInt idx = iItems.Count();
       
   437     while (--idx >= 0)
       
   438     {
       
   439         if (iItems[idx]->IsSelectable())
       
   440         {
       
   441             return iItems[idx];
       
   442         }
       
   443     }
       
   444     return NULL;
       
   445 }
       
   446 
       
   447 // typically just used when cleaning up. This won't cause a layout.
       
   448 TBool CMIDFormRow::RemoveItemIfExists(CMIDControlItem& aItem)
       
   449 {
       
   450     TInt i = -1;
       
   451     while (++i < iItems.Count())
       
   452     {
       
   453         if (&aItem == iItems[i])
       
   454         {
       
   455             iItems.Remove(i);
       
   456             return ETrue;
       
   457         }
       
   458     }
       
   459 
       
   460     return EFalse;
       
   461 }
       
   462 
       
   463 TInt CMIDFormRow::CurrentWidth()
       
   464 {
       
   465     return iCurrentWidth;
       
   466 }
       
   467 
       
   468 CMIDFormRow::CMIDFormRow(CMIDForm& aForm)
       
   469         :iForm(aForm)
       
   470 {
       
   471 #ifdef RD_SCALABLE_UI_V2
       
   472     SetAllowStrayPointers();
       
   473 #endif
       
   474 }
       
   475 
       
   476 void CMIDFormRow::ConstructL()
       
   477 {
       
   478 }
       
   479 
       
   480 /**
       
   481  *  Returns true if this row has at least an item which is not a spacer
       
   482  */
       
   483 TBool CMIDFormRow::HasNonSpacerItems() const
       
   484 {
       
   485     TBool ret = EFalse;
       
   486 
       
   487     TInt i = -1;
       
   488     while (++i < iItems.Count())
       
   489     {
       
   490         if (iItems[i]->Type() != MMIDComponent::ESpacer)
       
   491         {
       
   492             ret = ETrue;
       
   493             break;
       
   494         }
       
   495     }
       
   496 
       
   497     return ret;
       
   498 }
       
   499 
       
   500 // End of File