Button::Button() { imageView.reset(new ImageView); imageView->name("buttonIcon"); imageView->resizeOnImageChange = false; imageView->composite(false); imageView->backgroundColor(whiteColor); addSubview(imageView); titleLabel.reset(new Label); titleLabel->backgroundColor(clearColor); titleLabel->name("buttonTitle"); titleLabel->composite(false); addSubview(titleLabel); _state = ButtonStateReleased; updateFromState(); addEventHandler(ET_MouseDown, [this](Event* event) { mouseDown(event); }, EP_Bubble); addEventHandler(ET_MouseUpInside , [this](Event* event) { mouseUpInside(event); }, EP_Bubble); addEventHandler(ET_MouseUpOutside, [this](Event* event) { mouseUpOutside(event); }, EP_Bubble); name("Button"); layer->composite(true); }
void CAAutoCollectionView::reloadData() { if (m_pCollectionViewDataSource == NULL) return; this->reloadViewSizeData(); this->removeAllSubviews(); DRect winRect = this->getBounds(); winRect.origin = getContentOffset(); int dw = winRect.size.width - 2 * ((m_pCollectionViewOrientation == CACollectionViewOrientationVertical) ? m_iHoriMargins : m_iVertMargins); if (m_nCollectionHeaderHeight > 0 && m_pCollectionHeaderView) { m_pCollectionHeaderView->setDisplayRange(true); if (m_pCollectionViewOrientation == CACollectionViewOrientationVertical) { m_pCollectionHeaderView->setFrame(DRect(m_iHoriMargins, m_iVertMargins, dw, m_nCollectionHeaderHeight)); } else { m_pCollectionHeaderView->setFrame(DRect(m_iHoriMargins, m_iVertMargins, m_nCollectionHeaderHeight, dw)); } addSubview(m_pCollectionHeaderView); } int dwValue = calculateAllRects(); if (m_nCollectionFooterHeight > 0 && m_pCollectionFooterView) { if (m_pCollectionViewOrientation == CACollectionViewOrientationVertical) { m_pCollectionFooterView->setFrame(DRect(m_iHoriMargins, dwValue, dw, m_nCollectionFooterHeight)); } else { m_pCollectionFooterView->setFrame(DRect(dwValue, m_iVertMargins, m_nCollectionFooterHeight, dw)); } addSubview(m_pCollectionFooterView); } this->updateSectionHeaderAndFooterRects(); this->layoutPullToRefreshView(); this->startDeaccelerateScroll(); this->loadCollectionCell(); }
void CAPageControl::onEnter() { CAControl::onEnter(); if (m_pIndicators.size() != m_numberOfPages) { m_pIndicators.clear(); for (int i=0; i<m_numberOfPages; i++) { CAImageView* view; if (i == m_currentPage) { view = CAImageView::createWithImage(m_pSelectPageImage); view->setColor(m_currentPageIndicatorTintColor); } else { view = CAImageView::createWithImage(m_pPageImage); view->setColor(m_pageIndicatorTintColor); } CCRect rect; float width = getFrame().size.width/m_numberOfPages; rect.origin.x = i * width + width/2; rect.origin.y = getFrame().size.height/2; view->setCenterOrigin(rect.origin); addSubview(view); m_pIndicators.pushBack(view); } } }
void View::bringSubviewToFront(const ViewPtr& view) { auto pos = find(subviews.begin(), subviews.end(), view); if(pos != subviews.end()) { removeSubview(view); addSubview(view); } }
bool CATextSelectView::init() { if (!CAView::init()) return false; m_pTextViewMask = CAView::createWithColor(ccc4(60, 120, 240, 127)); addSubview(m_pTextViewMask); m_pTextViewMask->setVisible(false); m_pCursorMarkL = CAImageView::createWithImage(CAImage::create("source_material/text_pos_l.png")); addSubview(m_pCursorMarkL); m_pCursorMarkL->setVisible(false); m_pCursorMarkR = CAImageView::createWithImage(CAImage::create("source_material/text_pos_r.png")); addSubview(m_pCursorMarkR); m_pCursorMarkR->setVisible(false); return true; }
void CAListView::reloadData() { if (m_pListViewDataSource == NULL) return; this->reloadViewSizeData(); this->removeAllSubviews(); DRect winRect = this->getBounds(); winRect.origin = this->getContentOffset(); if (m_nListHeaderHeight > 0) { if (m_pListHeaderView) { m_pListHeaderView->setFrame(m_rHeaderRect); addSubview(m_pListHeaderView); } } unsigned int cellCount = m_pListViewDataSource->numberOfIndex(this); for (unsigned i = 0; i < cellCount; i++) { if (m_nIndexs > 0) { m_mpUsedListCells.insert(std::make_pair(i, (CAListViewCell*)NULL)); } } if (m_nListFooterHeight > 0) { if (m_pListFooterView) { m_pListFooterView->setFrame(m_rFooterRect); addSubview(m_pListFooterView); } } loadCollectionCell(); this->layoutPullToRefreshView(); this->startDeaccelerateScroll(); }
void CATextSelViewEx::showTextViewMark(const std::vector<CCRect>& vt) { hideTextViewMark(); for (int i = 0; i < vt.size(); i++) { CAView* pTextMaskView = CAView::createWithColor(ccc4(60, 120, 240, 127)); pTextMaskView->setFrame(vt[i]); addSubview(pTextMaskView); m_pTextViewMask.push_back(pTextMaskView); } this->setVisible(true); }
void Square::setup() { setAlignment(po::scene::Alignment::CENTER_CENTER); // Create and add a shape for the active state mActive = ShapeView::createRect(100, 100); mActive->setFillColor(mActiveColor); addSubview(mActive); // Create and add a shape for the selected state // Set the alpha to 0 so we can animate it mSelected = ShapeView::createRect(100, 100); mSelected->setFillColor(mSelectedColor); addSubview(mSelected); mSelected->setAlpha(0.f); // Connect to mouse events getSignal(MouseEvent::DOWN_INSIDE).connect(std::bind(&Square::onMouseEvent, this, std::placeholders::_1)); getSignal(MouseEvent::UP_INSIDE).connect(std::bind(&Square::onMouseEvent, this, std::placeholders::_1)); getSignal(MouseEvent::UP).connect(std::bind(&Square::onMouseEvent, this, std::placeholders::_1)); }
void ScrollView::setup() { // Create content view mContentView = po::scene::View::create( "UI Scroll View Content View" ); addSubview( mContentView ); // Subscribe to events if( mMouseEventsEnabled ) { enableMouseEvents(); } if( mTouchEventsEnabled ) { enableTouchEvents(); } mInitialized = true; }
bool CATextArrowView::init() { if (!CAView::init()) return false; m_pArrowView = CAImageView::createWithImage(CAImage::create("source_material/arrow.png")); addSubview(m_pArrowView); m_pArrowView->setVisible(false); m_pArrowView->setFrame(CCRectMake(0, 0, CATextArrowViewWidth, CATextArrowViewHeight)); m_pArrowView->setAlpha(0.5f); return true; }
void CAListView::loadCell() { DRect rect = this->getBounds(); rect.origin = getContentOffset(); rect.origin.y -= rect.size.height * 0.1f; rect.origin.x -= rect.size.width * 0.1f; rect.size.width *= 1.2f; rect.size.height *= 1.2f; std::map<unsigned int, CAListViewCell*>::iterator itr; for (itr = m_mpUsedListCells.begin(); itr != m_mpUsedListCells.end(); itr++) { CC_CONTINUE_IF(itr->second != NULL); unsigned int index = itr->first; DRect cellRect = m_rIndexRects[index]; CC_CONTINUE_IF(!rect.intersectsRect(cellRect)); CAListViewCell* cell = m_pListViewDataSource->listViewCellAtIndex(this, cellRect.size, index); if (cell) { cell->m_nIndex = index; cell->updateDisplayedAlpha(this->getAlpha()); addSubview(cell); cell->setFrame(cellRect); m_mpUsedListCells[index] = cell; m_vpUsedListCells.pushBack(cell); } if (m_pSelectedListCells.count(index)) { cell->setControlState(CAControlStateSelected); } if (m_pListViewDataSource) { m_pListViewDataSource->listViewWillDisplayCellAtIndex(this, cell, index); } CAView* view = this->dequeueReusableLine(); DRect lineRect = m_rLineRects[index]; if (view == NULL) { view = CAView::createWithFrame(lineRect, m_obSeparatorColor); } m_pUsedLines[index] = view; this->insertSubview(view, 1); view->setFrame(lineRect); } }
bool CADatePickerView::init() { if (!CAControl::init()) { return false; } m_pPickerView = new CAPickerView(); m_pPickerView->initWithFrame(this->getBounds()); m_pPickerView->setPickerViewDelegate(this); m_pPickerView->setPickerViewDataSource(this); m_pPickerView->setFontSizeNormal(40); m_pPickerView->setFontSizeSelected(40); addSubview(m_pPickerView); struct timeval tp = {0}; gettimeofday(&tp, NULL); time_t time = tp.tv_sec; m_tTM = *localtime(&time); return true; }
void CAAlertView::setCtrlImage(CAScale9ImageView*& pImageView, CAImage* image) { if (pImageView) { removeSubview(pImageView); } CC_SAFE_DELETE(pImageView); pImageView = new CAScale9ImageView(); CC_RETURN_IF(pImageView == NULL); if (!pImageView->initWithImage(image)) { CC_SAFE_DELETE(pImageView); return; } addSubview(pImageView); }
bool CADatePickerView::init() { if (!CAControl::init()) { return false; } m_pPickerView = CAPickerView::create(); m_pPickerView->retain(); m_pPickerView->setDataSource(this); m_pPickerView->setDelegate(this); m_pPickerView->setFontSizeNormal(40 * CAApplication::getApplication()->getAdaptationRatio()); m_pPickerView->setFontSizeSelected(40 * CAApplication::getApplication()->getAdaptationRatio()); addSubview(m_pPickerView); struct timeval tp = {0}; gettimeofday(&tp, NULL); time_t time = tp.tv_sec; m_tTM = *localtime(&time); return true; }
void CAListView::reloadData() { if (m_pListViewDataSource == NULL) return; this->reloadViewSizeData(); this->removeAllSubviews(); m_pUsedLines.clear(); m_pUsedListCells.clear(); m_pFreedListCells.clear(); m_pSelectedListCells.clear(); CCRect winRect = this->getBounds(); winRect.origin = this->getContentOffset(); if (m_nListHeaderHeight > 0) { if (m_pListHeaderView) { m_pListHeaderView->setFrame(m_rHeaderRect); addSubview(m_pListHeaderView); } } unsigned int cellCount = m_pListViewDataSource->numberOfIndex(this); for (unsigned i = 0; i < cellCount; i++) { if (m_nIndexs > 0) { std::pair<std::map<unsigned int, CAListViewCell*>::iterator, bool> itrResult = m_pUsedListCells.insert(std::make_pair(i, (CAListViewCell*)NULL)); CC_CONTINUE_IF(!winRect.intersectsRect(m_rIndexRects[i])); CAListViewCell* pCellView = m_pListViewDataSource->listViewCellAtIndex(this, m_rIndexRects[i].size, i); if (pCellView) { pCellView->m_nIndex = i; pCellView->setFrame(m_rIndexRects[i]); addSubview(pCellView); itrResult.first->second = pCellView; } } if (m_nSeparatorViewHeight > 0) { CAView* view = CAView::createWithFrame(m_rLineRects[i], m_obSeparatorColor); addSubview(view); m_pUsedLines[i] = view; } } if (m_nListFooterHeight > 0) { if (m_pListFooterView) { m_pListFooterView->setFrame(m_rFooterRect); addSubview(m_pListFooterView); } } this->layoutPullToRefreshView(); this->startDeaccelerateScroll(); }
void CACollectionView::reloadData() { CC_RETURN_IF(m_pCollectionViewDataSource == NULL); this->reloadViewSizeData(); this->removeAllSubviews(); DRect winRect = this->getBounds(); winRect.origin = getContentOffset(); float width = winRect.size.width; int y = 0; if (m_nCollectionHeaderHeight > 0 && m_pCollectionHeaderView) { m_pCollectionHeaderView->setDisplayRange(true); m_pCollectionHeaderView->setFrame(DRect(0, y, width, m_nCollectionHeaderHeight)); addSubview(m_pCollectionHeaderView); y += m_nCollectionHeaderHeight; } ; int begin = (int)m_rSectionRects.size(); m_rSectionRects.resize(m_rSectionRects.size() + m_nSections); for (int i = 0; i < m_nSections; i++) { unsigned int iSectionHeaderHeight = m_nSectionHeaderHeights.at(i); DRect sectionHeaderRect = DRect(0, y, width, iSectionHeaderHeight); if (iSectionHeaderHeight>0) { CAView* pSectionHeaderView = m_pCollectionViewDataSource->collectionViewSectionViewForHeaderInSection(this, sectionHeaderRect.size, i); if (pSectionHeaderView != NULL) { pSectionHeaderView->setDisplayRange(true); pSectionHeaderView->setFrame(sectionHeaderRect); insertSubview(pSectionHeaderView, 1); m_pSectionHeaderViews[i] = pSectionHeaderView; y += iSectionHeaderHeight; } } y += m_nVertInterval; unsigned int rowCount = m_nRowsInSections.at(i); for (int j = 0; j < rowCount; j++) { int iHeight = m_nRowHeightss.at(i).at(j); unsigned int itemCount = m_pCollectionViewDataSource->numberOfItemsInRowsInSection(this, i, j); unsigned int cellWidth = 0; if (itemCount>0) { cellWidth = (width - m_nHoriInterval) / itemCount - m_nHoriInterval; } for (int k = 0; k < itemCount; k++) { CAIndexPath3E indexPath = CAIndexPath3E(i, j, k); DRect cellRect = DRect(m_nHoriInterval + (cellWidth + m_nHoriInterval)*k, y, cellWidth, iHeight); m_rUsedCollectionCellRects[indexPath] = cellRect; std::pair<std::map<CAIndexPath3E, CACollectionViewCell*>::iterator, bool> itrResult = m_mpUsedCollectionCells.insert(std::make_pair(indexPath, (CACollectionViewCell*)NULL)); CC_CONTINUE_IF(!winRect.intersectsRect(cellRect)); CACollectionViewCell* cell = m_pCollectionViewDataSource->collectionCellAtIndex(this, cellRect.size, i, j, k); if (cell) { addSubview(cell); cell->setFrame(cellRect); cell->m_nSection = i; cell->m_nRow = j; cell->m_nItem = k; itrResult.first->second = cell; m_vpUsedCollectionCells.pushBack(cell); if (m_pCollectionViewDataSource) { m_pCollectionViewDataSource->collectionViewWillDisplayCellAtIndex(this, cell, i, j, k); } } } y += (iHeight + m_nVertInterval); } unsigned int iSectionFooterHeight = m_nSectionFooterHeights.at(i); DRect sectionFooterRect = DRect(0, y, width, iSectionFooterHeight); if (iSectionFooterHeight > 0) { CAView* pSectionFooterView = m_pCollectionViewDataSource->collectionViewSectionViewForFooterInSection(this, sectionFooterRect.size, i); if (pSectionFooterView != NULL) { pSectionFooterView->setDisplayRange(true); pSectionFooterView->setFrame(sectionFooterRect); insertSubview(pSectionFooterView, 1); m_pSectionFooterViews[i] = pSectionFooterView; y += iSectionFooterHeight; } } DRect sectionRect = sectionHeaderRect; sectionRect.size.height = sectionFooterRect.origin.y + sectionFooterRect.size.height - sectionHeaderRect.origin.y; m_rSectionRects[begin + i] = sectionRect; } if (m_nCollectionFooterHeight > 0 && m_pCollectionFooterView) { m_pCollectionFooterView->setFrame(DRect(0, y, width, m_nCollectionFooterHeight)); addSubview(m_pCollectionFooterView); y += m_nCollectionFooterHeight; } this->updateSectionHeaderAndFooterRects(); this->layoutPullToRefreshView(); this->startDeaccelerateScroll(); }
void CAStepper::onEnter() { CAControl::onEnter(); if (m_value<m_minimumValue) { m_value = m_minimumValue; } // init Background if (!m_pBackgroundImageView && m_pBackgroundImage[CAControlStateNormal]) { m_pBackgroundImageView = CAScale9ImageView::createWithImage(m_pBackgroundImage[CAControlStateNormal]); m_pBackgroundImageView->retain(); m_pBackgroundImageView->setCenter(DRect(getFrame().size.width/2, getFrame().size.height/2,getFrame().size.width,getFrame().size.height)); addSubview(m_pBackgroundImageView); } // init divider if (!m_pDividerImageView ) { m_pDividerImageView = CAImageView::createWithColor(m_cTintColor); m_pDividerImageView->retain(); if (m_pCAStepperOrientation==CAStepperOrientationHorizontal) { m_pDividerImageView->setCenter(DRect(getBounds().size.width/2, getBounds().size.height/2, LINE_WIDTH, getBounds().size.height)); } else { m_pDividerImageView->setCenter(DRect(getBounds().size.width/2, getBounds().size.height/2, getBounds().size.width, LINE_WIDTH)); } addSubview(m_pDividerImageView); } //float div = (m_pDividerImageView) ? m_pDividerImageView->getBounds().size.width/2 : 0; // init increment if (!m_pIncrementImageView && m_pIncrementImage[CAControlStateNormal]) { m_pIncrementImageView = CAImageView::createWithImage(m_pIncrementImage[CAControlStateNormal]); m_pIncrementImageView->retain(); if (m_pCAStepperOrientation==CAStepperOrientationHorizontal) { int tempw = MIN(getBounds().size.width, getBounds().size.height); m_pIncrementImageView->setImageViewScaleType(CAImageViewScaleTypeFitViewByHorizontal); m_pIncrementImageView->setCenter(DRect(getBounds().size.width/4*3, getBounds().size.height/2, tempw, tempw)); }else{ int tempw = MIN(getBounds().size.width, getBounds().size.height); m_pIncrementImageView->setImageViewScaleType(CAImageViewScaleTypeFitViewByVertical); m_pIncrementImageView->setCenter(DRect(getBounds().size.width/2, getBounds().size.height/4, tempw, tempw)); } insertSubview(m_pIncrementImageView,10); } // init decrement if (!m_pDecrementImageView && m_pDecrementImage[CAControlStateNormal]) { m_pDecrementImageView = CAImageView::createWithImage(m_pDecrementImage[CAControlStateNormal]); m_pDecrementImageView->retain(); if (m_pCAStepperOrientation==CAStepperOrientationHorizontal) { int tempw = MIN(getBounds().size.width, getBounds().size.height); m_pDecrementImageView->setImageViewScaleType(CAImageViewScaleTypeFitViewByHorizontal); m_pDecrementImageView->setCenter(DRect(getBounds().size.width/4, getBounds().size.height/2, tempw, tempw)); }else{ int tempw = MIN(getBounds().size.width, getBounds().size.height); m_pDecrementImageView->setImageViewScaleType(CAImageViewScaleTypeFitViewByVertical); m_pDecrementImageView->setCenter(DRect(getBounds().size.width/2, getBounds().size.height/4*3, tempw, tempw)); } insertSubview(m_pDecrementImageView,10); } }
void CAPickerView::reloadAllComponents() { if (m_delegate && m_dataSource) { // clear old data m_tableViews.clear(); m_selected.clear(); m_componentsIndex.clear(); m_displayRow.clear(); // clear all tableviews removeAllSubviews(); // reload data int component = m_dataSource->numberOfComponentsInPickerView(this); float total_width = calcTotalWidth(component); m_componentsIndex.resize(component); m_componentOffsetX.resize(component); m_displayRow.resize(component); float start_x = getFrame().size.width/2 - total_width/2; for (int i=0; i<component; i++) { m_selected.push_back(0); m_componentsIndex[i] = std::vector<int>(); m_componentOffsetX[i] = start_x; m_displayRow[i] = getFrame().size.height/m_dataSource->rowHeightForComponent(this, i); if (m_displayRow[i] % 2 == 0) { m_displayRow[i] += 1; } // create tableview float tableWidth = m_dataSource->widthForComponent(this, i); float tableHeight = m_dataSource->rowHeightForComponent(this, i) * m_displayRow[i]; float start_y = getFrame().size.height/2 - tableHeight/2; CATableView* tableView = CATableView::createWithFrame(CCRect(start_x, start_y, tableWidth, tableHeight)); tableView->setTableViewDataSource(this); tableView->setScrollViewDelegate(this); tableView->setSeparatorViewHeight(0); tableView->setSeparatorColor(CAColor_clear); tableView->setShowsScrollIndicators(false); m_tableViews.pushBack(tableView); addSubview(tableView); // create highlight CCSize selectSize = CCSizeMake(tableWidth, m_dataSource->rowHeightForComponent(this, i)); CAView* select = m_dataSource->viewForSelect(this, i, selectSize); if (!select) { CCRect sepRect = CCRectMake(start_x, getFrame().size.height/2 - m_dataSource->rowHeightForComponent(this, i)/2, tableWidth, 1); addSubview(CAView::createWithFrame(sepRect, m_separateColor)); sepRect.origin.y += m_dataSource->rowHeightForComponent(this, i); addSubview(CAView::createWithFrame(sepRect, m_separateColor)); } else { select->setCenter(CCRectMake(start_x, getFrame().size.height/2, selectSize.width, selectSize.height)); addSubview(select); } reloadComponent(1,i, true); start_x += m_dataSource->widthForComponent(this, i); } } }
void CAAlertView::calcuCtrlsSize() { CCSize winSize = CAApplication::getApplication()->getWinSize(); CCSize ertSize = getAlertWinSize(); bool isHoriBtnArray = m_vAllBtn.size() <= MAX_BUTTON_COUNT_ROW; if (!isHoriBtnArray) { ertSize.height += ertSize.height / 5; } if (m_pTitleImage) { if (isHoriBtnArray) { m_pTitleImage->setCenter(CCRectMake(winSize.width / 2, winSize.height / 2 - ertSize.height * 2 / 5, ertSize.width, ertSize.height / 5)); } else { m_pTitleImage->setCenter(CCRectMake(winSize.width / 2, winSize.height / 2 - ertSize.height * 5 / 12, ertSize.width, ertSize.height / 6)); } if (m_pTitleLabel) { m_pTitleLabel->setBounds(CCRectZero); } } if (m_pTitleLabel) { if (isHoriBtnArray) { m_pTitleLabel->setCenter(CCRectMake(winSize.width / 2, winSize.height / 2 - ertSize.height * 2 / 5, ertSize.width, ertSize.height / 5)); } else { m_pTitleLabel->setCenter(CCRectMake(winSize.width / 2, winSize.height / 2 - ertSize.height * 5 / 12, ertSize.width, ertSize.height / 6)); } float size = m_pTitleImage->getBounds().size.height / 2; m_pTitleLabel->setFontSize(size); } if (m_pContentBkImage) { if (isHoriBtnArray) { m_pContentBkImage->setCenter(CCRectMake(winSize.width / 2, winSize.height / 2, ertSize.width, ertSize.height * 3 / 5)); } else { m_pContentBkImage->setCenter(CCRectMake(winSize.width / 2, winSize.height / 2 - ertSize.height/6, ertSize.width, ertSize.height * 1 / 3)); } } if (m_pContentLabel) { if (isHoriBtnArray) { m_pContentLabel->setCenter(CCRectMake(winSize.width / 2, winSize.height / 2, ertSize.width, ertSize.height * 3 / 5)); } else { m_pContentLabel->setCenter(CCRectMake(winSize.width / 2, winSize.height / 2 - ertSize.height / 6, ertSize.width, ertSize.height * 1 / 3)); } float size = m_pTitleImage->getBounds().size.height / 2; m_pContentLabel->setFontSize(size); } if (!isHoriBtnArray) { m_pBtnTableView = new CATableView(); CCAssert(m_pBtnTableView != NULL, ""); m_pBtnTableView->initWithFrame(CCRectMake(0, 0, 0, 0)); m_pBtnTableView->setCenter(CCRectMake(winSize.width/2, winSize.height/2+ertSize.height/4, ertSize.width, ertSize.height/2)); m_pBtnTableView->setTableViewDataSource(this); m_pBtnTableView->setTableViewDelegate(this); addSubview(m_pBtnTableView); } for (int i = 0; i < m_vAllBtn.size(); i++) { CAButton* pButton = m_vAllBtn[i]; CCAssert(pButton, ""); if (isHoriBtnArray) { int iStartPosX = (winSize.width - ertSize.width) / 2; int iDtBtnWidth = ertSize.width / m_vAllBtn.size(); pButton->setCenter(CCRectMake(iStartPosX + iDtBtnWidth*i + iDtBtnWidth / 2, winSize.height / 2 + ertSize.height * 2 / 5, iDtBtnWidth, ertSize.height / 5)); addSubview(pButton); } else { pButton->setCenter(CCRectMake(0, 0, ertSize.width, ertSize.height / 6)); } } }