예제 #1
1
bool
QuickMenu::KeyPress(unsigned key_code)
{
  switch (key_code) {
  case KEY_LEFT:
    grid_view.MoveFocus(GridView::Direction::LEFT);
    break;

  case KEY_RIGHT:
    grid_view.MoveFocus(GridView::Direction::RIGHT);
    break;

  case KEY_UP:
    grid_view.MoveFocus(GridView::Direction::UP);
    break;

  case KEY_DOWN:
    grid_view.MoveFocus(GridView::Direction::DOWN);
    break;

  case KEY_MENU:
    grid_view.ShowNextPage();
    SetFocus();
    break;

  default:
    return false;
  }

  UpdateCaption();
  return true;
}
예제 #2
1
ArtistInfoWidget::ArtistInfoWidget( const Tomahawk::artist_ptr& artist, QWidget* parent )
    : QWidget( parent )
    , TomahawkUtils::DpiScaler( this )
    , ui( new Ui::ArtistInfoWidget )
    , m_artist( artist )
{
    m_widget = new QWidget;
    m_headerWidget = new BasicHeader;
    ui->setupUi( m_widget );

    {
        ui->relatedArtists->setAutoResize( true );
        ui->relatedArtists->setAutoFitItems( true );
        ui->relatedArtists->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
        ui->relatedArtists->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
        ui->relatedArtists->setItemWidth( scaledX( 170 ) );

        m_relatedModel = new PlayableModel( ui->relatedArtists );
        ui->relatedArtists->setPlayableModel( m_relatedModel );
        ui->relatedArtists->proxyModel()->sort( -1 );
        ui->relatedArtists->setEmptyTip( tr( "Sorry, we could not find any related artists!" ) );

        TomahawkStyle::stylePageFrame( ui->relatedArtists );
        TomahawkStyle::stylePageFrame( ui->artistFrame );
        TomahawkStyle::styleScrollBar( ui->relatedArtists->verticalScrollBar() );
    }

    {
        ui->albums->setAutoResize( true );
        ui->albums->setAutoFitItems( false );
        ui->albums->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
        ui->albums->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
        ui->albums->setWrapping( false );
        ui->albums->setItemWidth( scaledX( 190 ) );
        ui->albums->proxyModel()->setHideDupeItems( true );
        ui->albums->delegate()->setWordWrapping( true );
        ui->albums->setFixedHeight( ui->albums->itemSize().height() + ui->albums->spacing() * 2 );

        m_albumsModel = new PlayableModel( ui->albums );
        ui->albums->setPlayableModel( m_albumsModel );
        ui->albums->proxyModel()->sort( -1 );
        ui->albums->setEmptyTip( tr( "Sorry, we could not find any albums for this artist!" ) );

        TomahawkStyle::stylePageFrame( ui->albumFrame );
        TomahawkStyle::styleScrollBar( ui->albums->verticalScrollBar() );
        TomahawkStyle::styleScrollBar( ui->albums->horizontalScrollBar() );
    }

    {
        ui->topHits->setAutoResize( true );
        ui->topHits->setAutoFitItems( false );
        ui->topHits->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
        ui->topHits->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
        ui->topHits->setWrapping( false );
        ui->topHits->setItemWidth( scaledX( 140 ) );
        ui->topHits->proxyModel()->setHideDupeItems( true );
        ui->topHits->delegate()->setWordWrapping( true );
        ui->topHits->delegate()->setShowBuyButtons( true );
        ui->topHits->setFixedHeight( ui->topHits->itemSize().height() + ui->topHits->spacing() * 2 );

        m_topHitsModel = new PlayableModel( ui->topHits );
        ui->topHits->setPlayableModel( m_topHitsModel );
        ui->topHits->proxyModel()->sort( -1 );
        ui->topHits->setEmptyTip( tr( "Sorry, we could not find any top hits for this artist!" ) );

        TomahawkStyle::stylePageFrame( ui->trackFrame );
    }

    {
        ui->biography->setObjectName( "biography" );
        ui->biography->setContentsMargins( 0, 0, 0, 0 );
        ui->biography->page()->mainFrame()->setScrollBarPolicy( Qt::Horizontal, Qt::ScrollBarAlwaysOff );
        ui->biography->page()->mainFrame()->setScrollBarPolicy( Qt::Vertical, Qt::ScrollBarAsNeeded );
        ui->biography->page()->setLinkDelegationPolicy( QWebPage::DelegateAllLinks );
        ui->biography->installEventFilter( this );

        TomahawkStyle::stylePageWidget( ui->biography );
        TomahawkStyle::stylePageFrame( ui->bioFrame );

        connect( ui->biography, SIGNAL( linkClicked( QUrl ) ), SLOT( onBiographyLinkClicked( QUrl ) ) );

        QFont f = ui->topHitsMoreLabel->font();
        f.setWeight( QFont::Light );
        f.setPointSize( TomahawkUtils::defaultFontSize() + 1 );
        ui->topHitsMoreLabel->setFont( f );
        ui->albumsMoreLabel->setFont( f );

        connect( ui->albumsMoreLabel, SIGNAL( clicked() ), SLOT( onAlbumsMoreClicked() ) );
        connect( ui->topHitsMoreLabel, SIGNAL( clicked() ), SLOT( onTopHitsMoreClicked() ) );

        ui->cover->setFixedSize( scaled( QSize( 384, 384 ) ) );
    }

    {
        m_headerWidget->ui->anchor1Label->setText( tr( "Music" ) );
        m_headerWidget->ui->anchor2Label->setText( tr( "Biography" ) );
        m_headerWidget->ui->anchor3Label->setText( tr( "Related Artists" ) );
        m_headerWidget->ui->anchor1Label->show();
        m_headerWidget->ui->anchor2Label->show();
        m_headerWidget->ui->anchor3Label->show();

        QFontMetrics fm( m_headerWidget->ui->anchor1Label->font() );
        m_headerWidget->ui->anchor1Label->setFixedWidth( fm.width( m_headerWidget->ui->anchor1Label->text() ) + 16 );
        m_headerWidget->ui->anchor2Label->setFixedWidth( fm.width( m_headerWidget->ui->anchor2Label->text() ) + 16 );
        m_headerWidget->ui->anchor3Label->setFixedWidth( fm.width( m_headerWidget->ui->anchor3Label->text() ) + 16 );

        connect( m_headerWidget->ui->anchor1Label, SIGNAL( clicked() ), SLOT( onMusicAnchorClicked() ) );
        connect( m_headerWidget->ui->anchor2Label, SIGNAL( clicked() ), SLOT( onBioAnchorClicked() ) );
        connect( m_headerWidget->ui->anchor3Label, SIGNAL( clicked() ), SLOT( onRelatedArtistsAnchorClicked() ) );
    }

    m_stackedWidget = new QStackedWidget();

    {
        m_area = new QScrollArea();
        m_area->setWidgetResizable( true );
        m_area->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOn );
        m_area->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
        m_area->setWidget( m_widget );

        QPalette pal = palette();
        pal.setBrush( backgroundRole(), TomahawkStyle::PAGE_BACKGROUND );
        m_area->setPalette( pal );
        m_area->setAutoFillBackground( true );
        m_area->setFrameShape( QFrame::NoFrame );
        m_area->setAttribute( Qt::WA_MacShowFocusRect, 0 );

        m_stackedWidget->addWidget( m_area );

        connect( m_area->verticalScrollBar(), SIGNAL( valueChanged(int ) ), SLOT( onSliderValueChanged( int ) ) );
    }
    {
        ContextView* topHitsFullView = new ContextView( m_stackedWidget );
        topHitsFullView->setCaption( tr( "Songs" ) );
        topHitsFullView->setShowCloseButton( true );
        topHitsFullView->trackView()->setPlayableModel( m_topHitsModel );
        m_stackedWidget->addWidget( topHitsFullView );

        connect( topHitsFullView, SIGNAL( closeClicked() ), SLOT( onPageClosed() ) );
    }
    {
        GridView* albumsFullView = new GridView( m_stackedWidget );
        albumsFullView->delegate()->setWordWrapping( true );
        //        albumsFullView->setCaption( tr( "Albums" ) );
        //        albumsFullView->setShowCloseButton( true );
        albumsFullView->setPlayableModel( m_albumsModel );
        albumsFullView->proxyModel()->setHideDupeItems( true );

        CaptionLabel* captionLabel = new CaptionLabel( this );
        captionLabel->setText( tr( "Albums" ) );
        captionLabel->setShowCloseButton( true );

        QWidget* vbox = new QWidget;
        QPalette pal = vbox->palette();
        pal.setBrush( vbox->backgroundRole(), TomahawkStyle::PAGE_BACKGROUND );
        vbox->setPalette( pal );
        vbox->setAutoFillBackground( true );

        QVBoxLayout* vboxl = new QVBoxLayout;
        TomahawkUtils::unmarginLayout( vboxl );
        vboxl->setContentsMargins( 32, 32, 32, 32 );
        vboxl->setSpacing( scaledY( 8 ) );
        vbox->setLayout( vboxl );

        vboxl->addWidget( captionLabel );
        vboxl->addWidget( albumsFullView );
        vboxl->addStretch();
        vboxl->setStretchFactor( albumsFullView, 1 );

        m_stackedWidget->addWidget( vbox );

        connect( captionLabel, SIGNAL( clicked() ), SLOT( onPageClosed() ) );
    }

    {
        QVBoxLayout* layout = new QVBoxLayout();
        layout->addWidget( m_headerWidget );
        layout->addWidget( m_stackedWidget );
        setLayout( layout );
        TomahawkUtils::unmarginLayout( layout );
    }

    MetaPlaylistInterface* mpl = new MetaPlaylistInterface();
    mpl->addChildInterface( ui->relatedArtists->playlistInterface() );
    mpl->addChildInterface( ui->topHits->playlistInterface() );
    mpl->addChildInterface( ui->albums->playlistInterface() );
    m_plInterface = playlistinterface_ptr( mpl );

    onSliderValueChanged( 0 );

    TomahawkUtils::fixMargins( this );

    m_pixmap = TomahawkUtils::defaultPixmap( TomahawkUtils::DefaultArtistImage, TomahawkUtils::Original, scaled( QSize( 48, 48 ) ) );
    load( artist );
}
예제 #3
0
void SpaceHelper<BasisFunctionType>::getGlobalDofNormals_defaultImplementation(
    const GridView &view,
    const std::vector<std::vector<LocalDof>> &global2localDofs,
    std::vector<Point3D<CoordinateType>> &normals) {
  const int gridDim = view.dim();
  const int globalDofCount_ = global2localDofs.size();
  const int worldDim = view.dimWorld();
  normals.resize(globalDofCount_);

  const IndexSet &indexSet = view.indexSet();
  int elementCount = view.entityCount(0);

  arma::Mat<CoordinateType> elementNormals(worldDim, elementCount);
  std::unique_ptr<EntityIterator<0>> it = view.entityIterator<0>();
  arma::Col<CoordinateType> center(gridDim);
  // Note: we assume here that elements are flat and so the position at which
  // the normal is calculated does not matter.
  center.fill(0.5);
  arma::Col<CoordinateType> normal;
  while (!it->finished()) {
    const Entity<0> &e = it->entity();
    int index = indexSet.entityIndex(e);
    e.geometry().getNormals(center, normal);

    for (int dim = 0; dim < worldDim; ++dim)
      elementNormals(dim, index) = normal(dim);
    it->next();
  }

  if (gridDim == 1)
    for (size_t g = 0; g < globalDofCount_; ++g) {
      const std::vector<LocalDof> &ldofs = acc(global2localDofs, g);
      normals[g].x = 0.;
      normals[g].y = 0.;
      for (size_t l = 0; l < ldofs.size(); ++l) {
        normals[g].x += elementNormals(0, acc(ldofs, l).entityIndex);
        normals[g].y += elementNormals(1, acc(ldofs, l).entityIndex);
      }
      normals[g].x /= ldofs.size();
      normals[g].y /= ldofs.size();
    }
  else // gridDim == 2
    for (size_t g = 0; g < globalDofCount_; ++g) {
      const std::vector<LocalDof> &ldofs = acc(global2localDofs, g);
      normals[g].x = 0.;
      normals[g].y = 0.;
      normals[g].z = 0.;
      for (size_t l = 0; l < ldofs.size(); ++l) {
        normals[g].x += elementNormals(0, acc(ldofs, l).entityIndex);
        normals[g].y += elementNormals(1, acc(ldofs, l).entityIndex);
        normals[g].z += elementNormals(2, acc(ldofs, l).entityIndex);
      }
      normals[g].x /= ldofs.size();
      normals[g].y /= ldofs.size();
      normals[g].z /= ldofs.size();
    }
}
예제 #4
0
void
QuickMenu::UpdateCaption()
{
  StaticString<32> buffer;
  unsigned pageSize = grid_view.GetNumColumns() * grid_view.GetNumRows();
  unsigned lastPage = buttons.size() / pageSize;
  buffer.Format(_T("Quick Menu  %d/%d"),
                grid_view.GetCurrentPage() + 1, lastPage + 1);
  dialog.SetCaption(buffer);
}
예제 #5
0
void
QuickMenu::Prepare(ContainerWindow &parent, const PixelRect &rc)
{
  WindowStyle grid_view_style;
  grid_view_style.ControlParent();
  grid_view_style.Hide();

  const auto &dialog_look = UIGlobals::GetDialogLook();

  const auto &font = *dialog_look.button.font;
  const unsigned column_width = Layout::Scale(78u);
  const unsigned row_height =
    std::max(2 * (Layout::GetTextPadding() + font.GetHeight()),
             Layout::GetMaximumControlHeight());

  grid_view.Create(parent, dialog_look, rc, grid_view_style,
                   column_width, row_height);
  SetWindow(&grid_view);

  WindowStyle buttonStyle;
  buttonStyle.TabStop();

  for (unsigned i = 0; i < menu.MAX_ITEMS; ++i) {
    if (buttons.full())
      continue;

    const auto &menuItem = menu[i];
    if (!menuItem.IsDefined())
      continue;

    TCHAR buffer[100];
    const auto expanded =
      ButtonLabel::Expand(menuItem.label, buffer, ARRAY_SIZE(buffer));
    if (!expanded.visible)
      continue;

    PixelRect button_rc;
    button_rc.left = 0;
    button_rc.top = 0;
    button_rc.right = 80;
    button_rc.bottom = 30;
    auto *button = new Button(grid_view, button_rc, buttonStyle,
                              new QuickMenuButtonRenderer(dialog_look,
                                                          expanded.text),
                              *this, menuItem.event);
    button->SetEnabled(expanded.enabled);

    buttons.append(button);
    grid_view.AddItem(*button);
  }

  grid_view.RefreshLayout();
  UpdateCaption();
}
예제 #6
0
int main(int argc, char **argv)
{
    // Generate a new grid
    Grid grid(20, 20);
    grid.populate(200);

    // Generate a new GridView with the new grid
    GridView *win = new GridView(&grid, "Grid Viewer");
	
    // Show it
    win->show();
	
    // Run FLTK main loop
    return Fl::run();
}
예제 #7
0
void
SpaceHelper<BasisFunctionType>::getGlobalDofBoundingBoxes_defaultImplementation(
    const GridView &view,
    const std::vector<std::vector<LocalDof>> &global2localDofs,
    std::vector<BoundingBox<CoordinateType>> &bboxes) {
  const IndexSet &indexSet = view.indexSet();
  const int elementCount = view.entityCount(0);

  std::vector<arma::Mat<CoordinateType>> elementCorners(elementCount);
  std::unique_ptr<EntityIterator<0>> it = view.entityIterator<0>();
  while (!it->finished()) {
    const Entity<0> &e = it->entity();
    int index = indexSet.entityIndex(e);
    const Geometry &geo = e.geometry();
    geo.getCorners(acc(elementCorners, index));
    it->next();
  }

  BoundingBox<CoordinateType> model;
  const CoordinateType maxCoord = std::numeric_limits<CoordinateType>::max();
  model.lbound.x = model.lbound.y = model.lbound.z = maxCoord;
  model.ubound.x = model.ubound.y = model.ubound.z = -maxCoord;

  const int globalDofCount_ = global2localDofs.size();
  bboxes.resize(globalDofCount_, model);
  for (int i = 0; i < globalDofCount_; ++i) {
    const std::vector<LocalDof> &localDofs = acc(global2localDofs, i);
    BoundingBox<CoordinateType> &bbox = acc(bboxes, i);
    for (int j = 0; j < localDofs.size(); ++j)
      extendBoundingBox(bbox,
                        acc(elementCorners, acc(localDofs, j).entityIndex));
    assert(!localDofs.empty());
    setBoundingBoxReference<CoordinateType>(
        bbox, acc(elementCorners, localDofs[0].entityIndex)
                  .col(localDofs[0].dofIndex));
  }

#ifndef NDEBUG
  for (size_t i = 0; i < globalDofCount_; ++i) {
    assert(bboxes[i].reference.x >= bboxes[i].lbound.x);
    assert(bboxes[i].reference.y >= bboxes[i].lbound.y);
    assert(bboxes[i].reference.z >= bboxes[i].lbound.z);
    assert(bboxes[i].reference.x <= bboxes[i].ubound.x);
    assert(bboxes[i].reference.y <= bboxes[i].ubound.y);
    assert(bboxes[i].reference.z <= bboxes[i].ubound.z);
  }
#endif // NDEBUG
}
static const std::vector<bec::NodeId> selected_nodeids(GridView& g) {
  std::vector<int> rows = g.get_selected_rows();

  std::vector<bec::NodeId> entries;
  entries.reserve(rows.size());

  for (base::const_range<std::vector<int> > it(rows); it; ++it)
    entries.push_back((bec::NodeId)*it);

  return entries;
}
예제 #9
0
/* Generate new grid of width/height in new window */
void GridView::NewGrid(Fl_Widget *pButton)
{
    std::stringstream strValue;
    int width, height;
    
    // Get the width
    strValue << width_input->value();
    strValue >> width;
    
    // Clear for the height input
    strValue.clear();
    
    // Get the height
    strValue << height_input->value();
    strValue >> height;
    
    // Generate the new grid
    Grid *newGrid = new Grid(width, height);
    GridView *win = new GridView(newGrid, "Grid Viewer");
    
    win->show();
}
예제 #10
0
bool
QuickMenu::SetFocus()
{
  unsigned numColumns = grid_view.GetNumColumns();
  unsigned pageSize = numColumns * grid_view.GetNumRows();
  unsigned lastPage = buttons.size() / pageSize;
  unsigned currentPage = grid_view.GetCurrentPage();
  unsigned currentPageSize = currentPage == lastPage
    ? buttons.size() % pageSize
    : pageSize;
  unsigned centerCol = currentPageSize < numColumns
    ? currentPageSize / 2
    : numColumns / 2;
  unsigned centerRow = currentPageSize / numColumns / 2;
  unsigned centerPos = currentPage
    * pageSize + centerCol + centerRow * numColumns;

  if (centerPos >= buttons.size())
    return false;

  buttons[centerPos]->SetFocus();
  grid_view.RefreshLayout();
  return true;
}
예제 #11
0
Tomahawk::ViewPage*
ViewManager::show( const Tomahawk::collection_ptr& collection )
{
    qDebug() << Q_FUNC_INFO << m_currentMode;
    m_currentCollection = collection;
    ViewPage* shown = 0;
    if ( m_currentMode == PlaylistModes::Flat )
    {
/*        CollectionView* view;
        if ( !m_collectionViews.contains( collection ) || m_collectionViews.value( collection ).isNull() )
        {
            view = new CollectionView();
            CollectionFlatModel* model = new CollectionFlatModel();
            view->setPlayableModel( model );

            model->addCollection( collection );

            m_collectionViews.insert( collection, view );
        }
        else
        {
            view = m_collectionViews.value( collection ).data();
        }

        shown = view;
        setPage( view );*/
    }

    if ( m_currentMode == PlaylistModes::Tree )
    {
        TreeView* view;
        if ( !m_treeViews.contains( collection ) || m_treeViews.value( collection ).isNull() )
        {
            view = new TreeView();
            TreeModel* model = new TreeModel();
            view->setTreeModel( model );

            if ( collection && collection->source()->isLocal() )
                view->setEmptyTip( tr( "After you have scanned your music collection you will find your tracks right here." ) );
            else
                view->setEmptyTip( tr( "This collection is empty." ) );

            model->addCollection( collection );

            m_treeViews.insert( collection, view );
        }
        else
        {
            view = m_treeViews.value( collection ).data();
        }

        shown = view;
        setPage( view );
    }

    if ( m_currentMode == PlaylistModes::Album )
    {
        GridView* aview;
        if ( !m_collectionGridViews.contains( collection ) || m_collectionGridViews.value( collection ).isNull() )
        {
            aview = new GridView();
            AlbumModel* amodel = new AlbumModel( aview );
            aview->setPlayableModel( amodel );
            amodel->addCollection( collection );

            m_collectionGridViews.insert( collection, aview );
        }
        else
        {
            aview = m_collectionGridViews.value( collection ).data();
        }

        shown = aview;
        setPage( aview );
    }

    emit numSourcesChanged( 1 );

    return shown;
}
예제 #12
0
    void findPeriodicPartners(std::vector<BoundaryFaceInfo>& bfinfo,
                              std::array<double, 6>& side_areas,
                              const GridView& g,
                              const std::array<bool, 2*GridView::dimension>& is_periodic,
                              double spatial_tolerance = 1e-6)
    {
	// Pick out all boundary faces, simultaneously find the
	// bounding box of their centroids, and the max id.
        const int dim = GridView::dimension;
        typedef typename GridView::template Codim<0>::Iterator CI;
	typedef typename GridView::IntersectionIterator FI;
	typedef Dune::FieldVector<double, dim> Vector;
	std::vector<FI> bface_iters;
	Vector low(1e100);
	Vector hi(-1e100);
	int max_bid = 0;
	for (CI c = g.template begin<0>(); c != g.template end<0>(); ++c) {
	    for (FI f = g.ibegin(*c); f != g.iend(*c); ++f) {
		if (f->boundaryId()) {
		    bface_iters.push_back(f);
		    Vector fcent = f->geometry().center();
		    for (int dd = 0; dd < dim; ++dd) {
			low[dd] = std::min(low[dd], fcent[dd]);
			hi[dd] = std::max(hi[dd], fcent[dd]);
		    }
		    max_bid = std::max(max_bid, f->boundaryId());
		}
	    }
	}
	int num_bdy = bface_iters.size();
	if (max_bid != num_bdy) {
	    OPM_THROW(std::runtime_error, "createPeriodic() assumes that every boundary face has a unique boundary id. That seems to be violated.");
	}

	// Store boundary face info in a suitable structure. Also find side total volumes.
	std::fill(side_areas.begin(), side_areas.end(), 0.0);
	bfinfo.clear();
	bfinfo.reserve(num_bdy);
	for (int i = 0; i < num_bdy; ++i) {
	    BoundaryFaceInfo bf;
	    bf.face_index = i;
	    bf.bid = bface_iters[i]->boundaryId();
	    bf.canon_pos = -1;
	    bf.partner_face_index = -1;
	    bf.partner_bid = 0;
	    bf.area = bface_iters[i]->geometry().volume();
	    bf.centroid = bface_iters[i]->geometry().center();
	    for (int dd = 0; dd < dim; ++dd) {
		double coord = bf.centroid[dd];
		if (fabs(coord - low[dd]) <= spatial_tolerance) {
		    bf.canon_pos = 2*dd;
		    break;
		} else if (fabs(coord - hi[dd]) <= spatial_tolerance) {
		    bf.canon_pos = 2*dd + 1;
		    break;
		}
	    }
	    if (bf.canon_pos == -1) {
		std::cerr << "Centroid: " << bf.centroid << "\n";
		std::cerr << "Bounding box min: " << low << "\n";
		std::cerr << "Bounding box max: " << hi << "\n";
		OPM_THROW(std::runtime_error, "Boundary face centroid not on bounding box. Maybe the grid is not an axis-aligned shoe-box?");
	    }
	    side_areas[bf.canon_pos] += bf.area;
	    bf.centroid[bf.canon_pos/2] = 0.0;
	    bfinfo.push_back(bf);
	}
	assert(bfinfo.size() == bface_iters.size());

	// Sort the infos so that partners end up close.
	std::sort(bfinfo.begin(), bfinfo.end());

	// Identify partners.
	for (int i = 0; i < num_bdy; ++i) {
	    if (bfinfo[i].partner_face_index != -1) {
		continue;
	    }
	    if (!is_periodic[bfinfo[i].canon_pos]) {
		continue;
	    }
	    int lower = std::max(0, i - 10);
	    int upper = std::min(num_bdy, i + 10);
	    bool ok = match(bfinfo, i, lower, upper);
	    if (!ok) {
		// We have not found a partner.
		ok = match(bfinfo, i, 0, num_bdy);
		if (!ok) {
		    OPM_MESSAGE("Warning: No partner found for boundary id " << bfinfo[i].bid);
		    // OPM_THROW(std::runtime_error, "No partner found.");
		}
	    }
	}
    }