@@ -258,7 +258,7 @@ ImageViewer::ImageViewer(shared_ptr<Ipc> ipc, shared_ptr<SharedQueue<ImageAdditi
258258 // Fuzzy filter of open images
259259 {
260260 panel = new Widget{mSidebarLayout };
261- panel->setLayout (new BoxLayout {Orientation::Vertical, Alignment::Fill, 5 });
261+ panel->setLayout (new GridLayout {Orientation::Horizontal, 2 , Alignment::Fill, 5 , 2 });
262262
263263 mFilter = new TextBox{panel, " " };
264264 mFilter ->setEditable (true );
@@ -267,14 +267,23 @@ ImageViewer::ImageViewer(shared_ptr<Ipc> ipc, shared_ptr<SharedQueue<ImageAdditi
267267 return setFilter (filter);
268268 });
269269
270- mFilter ->setPlaceholder (" Enter text to filter images " );
270+ mFilter ->setPlaceholder (" Find " );
271271 mFilter ->setTooltip (tfm::format (
272272 " Filters visible images and layers according to a supplied string. "
273273 " The string must have the format 'image:layer'. "
274274 " Only images whose name contains 'image' and layers whose name contains 'layer' will be visible.\n\n "
275275 " Keyboard shortcut:\n %s+P" ,
276276 HelpWindow::COMMAND
277277 ));
278+
279+ mRegexButton = new Button{panel, " " , ENTYPO_ICON_SEARCH};
280+ mRegexButton ->setTooltip (" Treat filter as regular expression" );
281+ mRegexButton ->setPushed (false );
282+ mRegexButton ->setFlags (Button::ToggleButton);
283+ mRegexButton ->setFontSize (15 );
284+ mRegexButton ->setChangeCallback ([this ](bool value) {
285+ setUseRegex (value);
286+ });
278287 }
279288
280289 // Playback controls
@@ -1136,6 +1145,15 @@ bool ImageViewer::setFilter(const string& filter) {
11361145 return true ;
11371146}
11381147
1148+ bool ImageViewer::useRegex () {
1149+ return mRegexButton ->pushed ();
1150+ }
1151+
1152+ void ImageViewer::setUseRegex (bool value) {
1153+ mRegexButton ->setPushed (value);
1154+ mRequiresFilterUpdate = true ;
1155+ }
1156+
11391157void ImageViewer::maximize () {
11401158 glfwMaximizeWindow (mGLFWWindow );
11411159}
@@ -1270,11 +1288,11 @@ void ImageViewer::updateFilter() {
12701288 // This is the case if the image name matches the image part
12711289 // and at least one of the image's layers matches the layer part.
12721290 auto doesImageMatch = [&](const shared_ptr<Image>& image) {
1273- bool doesMatch = matches (image->name (), imagePart);
1291+ bool doesMatch = matches (image->name (), imagePart, useRegex () );
12741292 if (doesMatch) {
12751293 bool anyLayersMatch = false ;
12761294 for (const auto & layer : image->layers ()) {
1277- if (matches (layer, layerPart)) {
1295+ if (matches (layer, layerPart, useRegex () )) {
12781296 anyLayersMatch = true ;
12791297 break ;
12801298 }
@@ -1350,7 +1368,7 @@ void ImageViewer::updateFilter() {
13501368 selectImage (nthVisibleImage (0 ));
13511369 }
13521370
1353- if (mCurrentReference && !matches (mCurrentReference ->name (), imagePart)) {
1371+ if (mCurrentReference && !matches (mCurrentReference ->name (), imagePart, useRegex () )) {
13541372 selectReference (nullptr );
13551373 }
13561374 }
@@ -1362,13 +1380,13 @@ void ImageViewer::updateFilter() {
13621380 const auto & buttons = mLayerButtonContainer ->children ();
13631381 for (Widget* button : buttons) {
13641382 ImageButton* ib = dynamic_cast <ImageButton*>(button);
1365- ib->setVisible (matches (ib->caption (), layerPart));
1383+ ib->setVisible (matches (ib->caption (), layerPart, useRegex () ));
13661384 if (ib->visible ()) {
13671385 ib->setId (id++);
13681386 }
13691387 }
13701388
1371- if (!matches (mCurrentLayer , layerPart)) {
1389+ if (!matches (mCurrentLayer , layerPart, useRegex () )) {
13721390 selectLayer (nthVisibleLayer (0 ));
13731391 }
13741392 }
@@ -1383,6 +1401,7 @@ void ImageViewer::updateLayout() {
13831401 mSidebar ->setFixedHeight (mSize .y () - footerHeight);
13841402
13851403 mHelpButton ->setPosition (Vector2i{mSidebar ->fixedWidth () - 38 , 5 });
1404+ mFilter ->setFixedWidth (mSidebar ->fixedWidth () - 50 );
13861405 mSidebarLayout ->setFixedWidth (mSidebar ->fixedWidth ());
13871406
13881407 mVerticalScreenSplit ->setFixedSize (mSize );
0 commit comments