{ "translations": { "Storage is temporarily not available" : "Складиште привремено није доступно", "Storage invalid" : "Неисправно складиште", "Unknown error" : "Непозната грешка", "File could not be found" : "Фајл није нађен", "Move or copy" : "Помери или копирај", "Download" : "Преузми", "Delete" : "Обриши", "Home" : "Почетна", "Close" : "Затвори", "Favorites" : "Омиљени", "Could not create folder \"{dir}\"" : "Не могу да направим фасциклу „{dir}“", "This will stop your current uploads." : "Ово ће да прекине тренутна отпремања.", "Upload cancelled." : "Отпремање је отказано.", "Processing files …" : "Обрађујем фајлове…", "…" : "…", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Не могу да отпремим {filename} јер је то или директоријум или има 0 бајтова", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Нема простора. Отпремате {size1} али само {size2} је преостало", "Target folder \"{dir}\" does not exist any more" : "Одредишна фасцикла „{dir}“ више не постоји", "Not enough free space" : "Нема довољно слободног места", "An unknown error has occurred" : "Десила се непозната грешка", "Uploading …" : "Отпремам…", "{loadedSize} of {totalSize} ({bitrate})" : "{loadedSize} од {totalSize} ({bitrate})", "Uploading that item is not supported" : "Отпремање те ставке није подржано", "Target folder does not exist any more" : "Одредишна фасцикла више не постоји", "Operation is blocked by access control" : "Контрола приступа је блокирала операцију", "Error when assembling chunks, status code {status}" : "Грешки при прикупљању делова фајла, статус код {status}", "Actions" : "Радње", "Rename" : "Преименуј", "Copy" : "Копирај", "Choose target folder" : "Одаберите одредишну фасциклу", "Open" : "Отвори", "Delete file" : "Обриши фајл", "Delete folder" : "Обриши фасциклу", "Disconnect storage" : "Искључи складиште", "Leave this share" : "Напусти ово дељење", "Could not load info for file \"{file}\"" : "Не могу да учитам информације фајла „{file}“", "Files" : "Фајлови", "Details" : "Детаљи", "Show list view" : "Prikaži prikaz liste", "Show grid view" : "Prikaži prikaz mreže", "Pending" : "На чекању", "Unable to determine date" : "Не могу да одредим датум", "This operation is forbidden" : "Ова радња је забрањена", "This directory is unavailable, please check the logs or contact the administrator" : "Овај директоријум није доступан, проверите записе или контактирајте администратора", "Could not move \"{file}\", target exists" : "Не могу да померим „{file}“, одредиште већ постоји", "Could not move \"{file}\"" : "Не могу да померим „{file}“", "copy" : "копиран", "Could not copy \"{file}\", target exists" : "Не могу да копирам „{file}“, одредиште већ постоји", "Could not copy \"{file}\"" : "Не могу да копирам „{file}“", "Copied {origin} inside {destination}" : "Копиран {origin} у {destination}", "Copied {origin} and {nbfiles} other files inside {destination}" : "Копиран{origin} и још {nbfiles} других фајлова у {destination}", "{newName} already exists" : "{newName} већ постоји", "Could not rename \"{fileName}\", it does not exist any more" : "Не могу да преименујем „{fileName}“, фајл више не постоји", "The name \"{targetName}\" is already used in the folder \"{dir}\". Please choose a different name." : "Име „{targetName}“ се већ користи за фасциклу „{dir}“. Одаберите неко друго име.", "Could not rename \"{fileName}\"" : "Не могу да преименујем „{fileName}“", "Could not create file \"{file}\"" : "Не могу да направим фајл „{file}“", "Could not create file \"{file}\" because it already exists" : "Не могу да направим фајл „{file}“ јер већ постоји", "Could not create folder \"{dir}\" because it already exists" : "Не могу да направим фасциклу „{dir}“ јер већ постоји", "Could not fetch file details \"{file}\"" : "Не могу да дохватим детаље за „{file}“", "Error deleting file \"{fileName}\"." : "Грешка при брисању фајла „{fileName}“.", "No search results in other folders for {tag}{filter}{endtag}" : "Нема резултата претраге у осталим фасциклама за {tag}{filter}{endtag}", "Enter more than two characters to search in other folders" : "Унесите више од два карактера да претражујете у другим фасциклама", "Name" : "Назив", "Size" : "Величина", "Modified" : "Измењен", "_%n folder_::_%n folders_" : ["%n фасцикла","%n фасцикле","%n фасцикли"], "_%n file_::_%n files_" : ["%n фајл","%n фајла","%n фајлова"], "{dirs} and {files}" : "{dirs} и {files}", "_including %n hidden_::_including %n hidden_" : ["укључујући и %n скривени","укључујући и %n скривена","укључујући и %n скривених"], "_Uploading %n file_::_Uploading %n files_" : ["Отпремам %n фајл","Отпремам %n фајла","Отпремам %n фајлова"], "Select file range" : "Одаберите опсег фајлова", "{used} of {quota} used" : "{used} од {quota} искоришћено", "{used} used" : "{used} искоришћено", "\"{name}\" is an invalid file name." : "„{name}“ није исправан назив фајла.", "File name cannot be empty." : "Назив фајла не може бити празан.", "\"/\" is not allowed inside a file name." : "„/“ није дозвољен каракетер у имену фајла.", "\"{name}\" is not an allowed filetype" : "„{name}“ није дозвољени тип фајла", "Storage of {owner} is almost full ({usedSpacePercent}%)." : "Складиште корисника {owner} је скоро пуно ({usedSpacePercent}%).", "Group folder \"{mountPoint}\" is almost full ({usedSpacePercent}%)." : "Групна фасцикла „{mountPoint}“ је скоро пуна ({usedSpacePercent}%).", "External storage \"{mountPoint}\" is almost full ({usedSpacePercent}%)." : "Спољашње складиште „{mountPoint}“ је скоро пуно ({usedSpacePercent}%).", "Your storage is almost full ({usedSpacePercent}%)." : "Ваше складиште је скоро пуно ({usedSpacePercent}%).", "View in folder" : "Види у фасцикли", "Copied!" : "Копирано!", "Copy direct link (only works for users who have access to this file/folder)" : "Копирај директну везу (ради само за кориснике који имају приступ овом фајлу/фасциклу)", "Path" : "Путања", "_%n byte_::_%n bytes_" : ["%n бајт","%n бајта","%n бајтова"], "Favorited" : "Омиљено", "Favorite" : "Омиљени", "You can only favorite a single file or folder at a time" : "Можете поставити као омиљени само један фајл или фасциклу одједном", "New folder" : "Нова фасцикла", "Upload file" : "Отпреми фајл", "Recent" : "Скорашњи", "Not favorited" : "Није омиљено", "Remove from favorites" : "Избаци из омиљених", "Add to favorites" : "Додај у омиљене", "An error occurred while trying to update the tags" : "Дошло је до грешке при покушају ажурирања ознака", "Added to favorites" : "Додато у омиљено", "Removed from favorites" : "Избачено из омиљених", "You added {file} to your favorites" : "Додали сте {file} у омиљене", "You removed {file} from your favorites" : "Избацили сте {file} из омиљених", "File changes" : "Измене над фајлом", "Created by {user}" : "Направио {user}", "Changed by {user}" : "Изменио {user}", "Deleted by {user}" : "Обрисао {user}", "Restored by {user}" : "Повратио {user}", "Renamed by {user}" : "Преименовао {user}", "Moved by {user}" : "Померио {user}", "\"remote user\"" : "„удаљени корисник“", "You created {file}" : "Направили сте {file}", "You created an encrypted file in {file}" : "Направили сте шифровани фајл {file}", "{user} created {file}" : "{user} је направио {file}", "{user} created an encrypted file in {file}" : "{user} је направио шифровани фајл {file}", "{file} was created in a public folder" : "{file} је направљен у јавној фасцикли", "You changed {file}" : "Изменили сте {file}", "You changed an encrypted file in {file}" : "Изменили сте шифровани фајл {file}", "{user} changed {file}" : "{user} је изменио {file}", "{user} changed an encrypted file in {file}" : "{user} је изменио шифровани фајл {file}", "You deleted {file}" : "Обрисали сте {file}", "You deleted an encrypted file in {file}" : "Обрисали сте шифровани фајл {file}", "{user} deleted {file}" : "{user} је обрисао {file}", "{user} deleted an encrypted file in {file}" : "{user} је обрисао шифровани фајл {file}", "You restored {file}" : "Повратили сте {file}", "{user} restored {file}" : "{user} је повратио {file}", "You renamed {oldfile} to {newfile}" : "Преименовали сте {oldfile} на {newfile}", "{user} renamed {oldfile} to {newfile}" : "{user} је преименовао {oldfile} на {newfile}", "You moved {oldfile} to {newfile}" : "Померили сте {oldfile} на {newfile}", "{user} moved {oldfile} to {newfile}" : "{user} је померио {oldfile} на {newfile}", "A file has been added to or removed from your favorites" : "Фајл је додат или избрисан из Ваших омиљених", "A file or folder has been changed" : "Фајл или фасцикла су измењени", "A favorite file or folder has been changed" : "Омиљени фајл или фасцикла су измењени", "All files" : "Сви фајлови", "Unlimited" : "Неограничено", "Upload (max. %s)" : "Отпремање (макс. %s)", "Accept" : "Прихвати", "Reject" : "Одбаци", "Incoming ownership transfer from {user}" : "Надолазећи пренос власништва од корисника {user}", "Do you want to accept {path}?\n\nNote: The transfer process after accepting may take up to 1 hour." : "Да ли желите да прихватите {path}?\n\nПажња: После прихватања, процес трансфера може потрајати и до 1h.", "Ownership transfer failed" : "Пренос власништва није успео", "Your ownership transfer of {path} to {user} failed." : "Ваш пренос власништва {path} на корисника {user} није успео.", "The ownership transfer of {path} from {user} failed." : "Пренос власништва {path} на корисника {user} није успео.", "Ownership transfer done" : "Пренос власништва завршен", "Your ownership transfer of {path} to {user} has completed." : "Ваш пренос власништва {path} на корисника {user} завршен.", "The ownership transfer of {path} from {user} has completed." : "Пренос власништва {path} на корисника {user} завршен.", "in %s" : "за %s", "File Management" : "Управљање фајловима", "Transfer ownership of a file or folder" : "Пренеси власништво фајла или фасцикле", "Choose file or folder to transfer" : "Одаберите фајл или фасциклу за пренос", "Change" : "Измени", "New owner" : "Нови власник", "Search users" : "Претражи кориснике", "Choose a file or folder to transfer" : "Одаберите фајл или фасциклу за пренос", "Transfer" : "Пренеси", "Transfer {path} to {userid}" : "Пренеси {path} на корисника {userid}", "Invalid path selected" : "Одабрана неисправна путања", "Ownership transfer request sent" : "Послат захтев за пренос власништва", "Tags" : "Ознаке", "Unable to change the favourite state of the file" : "Неуспела промена стања омиљености фајла", "Error while loading the file data" : "Грешка при учитавању података фајла", "Cancel" : "Поништи", "Create" : "Направи", "%s used" : "%s искоришћено", "%1$s of %2$s used" : "Заузето %1$s од %2$s", "Show hidden files" : "Прикажи скривене фајлове", "WebDAV" : "ВебДАВ", "Use this address to access your Files via WebDAV" : "Користи ову адресу да приступате Вашим фајловима преко ВебДАВа", "Toggle grid view" : "Укључи/искључи приказ мреже", "No files in here" : "Овде нема фајлова", "Upload some content or sync with your devices!" : "Отпремите неки садржај или синхронизујте са вашим уређајима!", "No entries found in this folder" : "Нема ничега у овој фасцикли", "Select all" : "Означи све", "Upload too large" : "Фајл за отпремање је превелики", "The files you are trying to upload exceed the maximum size for file uploads on this server." : "Фајлови које желите да отпремите превазилазе ограничење отпремања на овом серверу.", "No favorites yet" : "Још нема омиљених", "Files and folders you mark as favorite will show up here" : "Фајлови и фасцикле које обележите као омиљене појавиће се овде", "Deleted files" : "Обрисани фајлови", "Shares" : "Дељења", "Shared with others" : "Дељени са осталима", "Shared with you" : "Дељени са вама", "Shared by link" : "Дељени путем везе", "Deleted shares" : "Обрисана дељења", "Pending shares" : "Дељења на чекању", "Text file" : "Tекстуални фајл", "New text file.txt" : "Нов текстуални фајл.txt", "Select" : "Изабери", "You don’t have permission to upload or create files here" : "Немате дозволе да овде отпремате или стварате фајлове", "New" : "Ново", "Cannot transfer ownership of a file or folder you don't own" : "Не можете пренети власништво фајла или фасцикле које нису Ваше", "%s%% of %s used" : "%s%% од %s искоришћено", "Settings" : "Поставке" },"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);" }274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517
/*
@ITMillApache2LicenseForJavaFiles@
 */

package com.vaadin.ui;

import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.vaadin.data.Container;
import com.vaadin.event.FieldEvents;
import com.vaadin.event.FieldEvents.BlurEvent;
import com.vaadin.event.FieldEvents.BlurListener;
import com.vaadin.event.FieldEvents.FocusEvent;
import com.vaadin.event.FieldEvents.FocusListener;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.Resource;
import com.vaadin.terminal.gwt.client.ui.VFilterSelect;

/**
 * <p>
 * A class representing a selection of items the user has selected in a UI. The
 * set of choices is presented as a set of {@link com.vaadin.data.Item}s in a
 * {@link com.vaadin.data.Container}.
 * </p>
 * 
 * <p>
 * A <code>Select</code> component may be in single- or multiselect mode.
 * Multiselect mode means that more than one item can be selected
 * simultaneously.
 * </p>
 * 
 * @author IT Mill Ltd.
 * @version
 * @VERSION@
 * @since 3.0
 */
@SuppressWarnings("serial")
@ClientWidget(VFilterSelect.class)
public class Select extends AbstractSelect implements AbstractSelect.Filtering,
        FieldEvents.BlurNotifier, FieldEvents.FocusNotifier {

    private static final String BLUR_EVENT_ID = VFilterSelect.BLUR_EVENT_IDENTIFIER;
    private static final String FOCUS_EVENT_ID = VFilterSelect.FOCUS_EVENT_IDENTIFIER;

    /**
     * Holds value of property pageLength. 0 disables paging.
     */
    protected int pageLength = 10;

    private int columns = 0;

    // Current page when the user is 'paging' trough options
    private int currentPage = -1;

    private int filteringMode = FILTERINGMODE_STARTSWITH;

    private String filterstring;
    private String prevfilterstring;
    private List filteredOptions;

    /**
     * Flag to indicate that request repaint is called by filter request only
     */
    private boolean optionRequest;

    /* Constructors */

    /* Component methods */

    public Select() {
        super();
    }

    public Select(String caption, Collection options) {
        super(caption, options);
    }

    public Select(String caption, Container dataSource) {
        super(caption, dataSource);
    }

    public Select(String caption) {
        super(caption);
    }

    /**
     * Paints the content of this component.
     * 
     * @param target
     *            the Paint Event.
     * @throws PaintException
     *             if the paint operation failed.
     */
    @Override
    public void paintContent(PaintTarget target) throws PaintException {
        if (isMultiSelect()) {
            // background compatibility hack. This object shouldn't be used for
            // multiselect lists anymore (ListSelect instead). This fallbacks to
            // a simpler paint method in super class.
            super.paintContent(target);
            return;
        }

        // clear caption change listeners
        getCaptionChangeListener().clear();

        // The tab ordering number
        if (getTabIndex() != 0) {
            target.addAttribute("tabindex", getTabIndex());
        }

        // If the field is modified, but not committed, set modified attribute
        if (isModified()) {
            target.addAttribute("modified", true);
        }

        // Adds the required attribute
        if (isRequired()) {
            target.addAttribute("required", true);
        }

        if (isNewItemsAllowed()) {
            target.addAttribute("allownewitem", true);
        }

        boolean needNullSelectOption = false;
        if (isNullSelectionAllowed()) {
            target.addAttribute("nullselect", true);
            needNullSelectOption = (getNullSelectionItemId() == null);
            if (!needNullSelectOption) {
                target.addAttribute("nullselectitem", true);
            }
        }

        // Constructs selected keys array
        String[] selectedKeys;
        if (isMultiSelect()) {
            selectedKeys = new String[((Set) getValue()).size()];
        } else {
            selectedKeys = new String[(getValue() == null
                    && getNullSelectionItemId() == null ? 0 : 1)];
        }

        target.addAttribute("pagelength", pageLength);

        target.addAttribute("filteringmode", getFilteringMode());

        // Paints the options and create array of selected id keys
        // TODO Also use conventional rendering if lazy loading is not supported
        // by terminal
        int keyIndex = 0;

        target.startTag("options");

        if (currentPage < 0) {
            optionRequest = false;
            currentPage = 0;
            filterstring = "";
        }

        List options = getFilteredOptions();
        options = sanitetizeList(options, needNullSelectOption);

        final boolean paintNullSelection = needNullSelectOption
                && (currentPage == 0 && (getFilteringMode() == FILTERINGMODE_OFF
                        || filterstring == null || filterstring.equals("")));

        if (paintNullSelection) {
            target.startTag("so");
            target.addAttribute("caption", "");
            target.addAttribute("key", "");
            target.endTag("so");
        }

        final Iterator i = options.iterator();
        // Paints the available selection options from data source

        while (i.hasNext()) {

            final Object id = i.next();

            if (!isNullSelectionAllowed() && id != null
                    && id.equals(getNullSelectionItemId()) && !isSelected(id)) {
                continue;
            }

            // Gets the option attribute values
            final String key = itemIdMapper.key(id);
            final String caption = getItemCaption(id);
            final Resource icon = getItemIcon(id);
            getCaptionChangeListener().addNotifierForItem(id);

            // Paints the option
            target.startTag("so");
            if (icon != null) {
                target.addAttribute("icon", icon);
            }
            target.addAttribute("caption", caption);
            if (id != null && id.equals(getNullSelectionItemId())) {
                target.addAttribute("nullselection", true);
            }
            target.addAttribute("key", key);
            if (isSelected(id) && keyIndex < selectedKeys.length) {
                target.addAttribute("selected", true);
                selectedKeys[keyIndex++] = key;
            }
            target.endTag("so");
        }
        target.endTag("options");

        target.addAttribute("totalitems", size()
                + (needNullSelectOption ? 1 : 0));
        if (filteredOptions != null) {
            target.addAttribute("totalMatches", filteredOptions.size()
                    + (needNullSelectOption ? 1 : 0));
        }

        // Paint variables
        target.addVariable(this, "selected", selectedKeys);
        if (isNewItemsAllowed()) {
            target.addVariable(this, "newitem", "");
        }

        target.addVariable(this, "filter", filterstring);
        target.addVariable(this, "page", currentPage);

        currentPage = -1; // current page is always set by client

        optionRequest = true;

        // Hide the error indicator if needed
        if (isRequired() && isEmpty() && getComponentError() == null
                && getErrorMessage() != null) {
            target.addAttribute("hideErrors", true);
        }
    }

    /**
     * Makes correct sublist of given list of options.
     * 
     * If paint is not an option request (affected by page or filter change),
     * page will be the one where possible selection exists.
     * 
     * Detects proper first and last item in list to return right page of
     * options. Also, if the current page is beyond the end of the list, it will
     * be adjusted.
     * 
     * @param options
     * @param needNullSelectOption
     *            flag to indicate if nullselect option needs to be taken into
     *            consideration
     */
    private List sanitetizeList(List options, boolean needNullSelectOption) {

        if (options.size() > pageLength) {
            int first = currentPage * pageLength;
            int last = first + pageLength;
            if (needNullSelectOption) {
                if (currentPage > 0) {
                    first--;
                }
                last--;
            }
            if (options.size() < last) {
                last = options.size();
            }
            if (!optionRequest) {
                // TODO ensure proper page
                if (!isMultiSelect()) {
                    Object selection = getValue();
                    if (selection != null) {
                        int index = options.indexOf(selection);
                        if (index != -1 && (index < first || index >= last)) {
                            int newPage = (index + (needNullSelectOption ? 1
                                    : 0))
                                    / pageLength;
                            currentPage = newPage;
                            return sanitetizeList(options, needNullSelectOption);
                        }
                    }
                }
            }

            // adjust the current page if beyond the end of the list
            if (first >= last && currentPage > 0) {
                currentPage -= (first - last + pageLength) / pageLength;
                return sanitetizeList(options, needNullSelectOption);
            }

            return options.subList(first, last);
        } else {
            return options;
        }
    }

    protected List getFilteredOptions() {
        if (filterstring == null || filterstring.equals("")
                || filteringMode == FILTERINGMODE_OFF) {
            prevfilterstring = null;
            filteredOptions = new LinkedList(getItemIds());
            return filteredOptions;
        }

        if (filterstring.equals(prevfilterstring)) {
            return filteredOptions;
        }

        Collection items;
        if (prevfilterstring != null
                && filterstring.startsWith(prevfilterstring)) {
            items = filteredOptions;
        } else {
            items = getItemIds();
        }
        prevfilterstring = filterstring;

        filteredOptions = new LinkedList();
        for (final Iterator it = items.iterator(); it.hasNext();) {
            final Object itemId = it.next();
            String caption = getItemCaption(itemId);
            if (caption == null || caption.equals("")) {
                continue;
            } else {
                caption = caption.toLowerCase();
            }
            switch (filteringMode) {
            case FILTERINGMODE_CONTAINS:
                if (caption.indexOf(filterstring) > -1) {
                    filteredOptions.add(itemId);
                }
                break;
            case FILTERINGMODE_STARTSWITH:
            default:
                if (caption.startsWith(filterstring)) {
                    filteredOptions.add(itemId);
                }
                break;
            }
        }

        return filteredOptions;
    }

    /**
     * Invoked when the value of a variable has changed.
     * 
     * @see com.vaadin.ui.AbstractComponent#changeVariables(java.lang.Object,
     *      java.util.Map)
     */
    @Override
    public void changeVariables(Object source, Map variables) {
        // Not calling super.changeVariables due the history of select
        // component hierarchy

        // Selection change
        if (variables.containsKey("selected")) {
            final String[] ka = (String[]) variables.get("selected");

            if (isMultiSelect()) {
                // Multiselect mode

                // TODO Optimize by adding repaintNotNeeded whan applicaple

                // Converts the key-array to id-set
                final LinkedList s = new LinkedList();
                for (int i = 0; i < ka.length; i++) {
                    final Object id = itemIdMapper.get(ka[i]);
                    if (id != null && containsId(id)) {
                        s.add(id);
                    }
                }

                // Limits the deselection to the set of visible items
                // (non-visible items can not be deselected)
                final Collection visible = getVisibleItemIds();
                if (visible != null) {
                    Set newsel = (Set) getValue();
                    if (newsel == null) {
                        newsel = new HashSet();
                    } else {
                        newsel = new HashSet(newsel);
                    }
                    newsel.removeAll(visible);
                    newsel.addAll(s);
                    setValue(newsel, true);
                }
            } else {
                // Single select mode
                if (ka.length == 0) {

                    // Allows deselection only if the deselected item is visible
                    final Object current = getValue();
                    final Collection visible = getVisibleItemIds();
                    if (visible != null && visible.contains(current)) {
                        setValue(null, true);
                    }
                } else {
                    final Object id = itemIdMapper.get(ka[0]);
                    if (id != null && id.equals(getNullSelectionItemId())) {
                        setValue(null, true);
                    } else {
                        setValue(id, true);
                    }
                }
            }
        }

        String newFilter;
        if ((newFilter = (String) variables.get("filter")) != null) {
            // this is a filter request
            currentPage = ((Integer) variables.get("page")).intValue();
            filterstring = newFilter;
            if (filterstring != null) {
                filterstring = filterstring.toLowerCase();
            }
            optionRepaint();
        } else if (isNewItemsAllowed()) {
            // New option entered (and it is allowed)
            final String newitem = (String) variables.get("newitem");
            if (newitem != null && newitem.length() > 0) {
                getNewItemHandler().addNewItem(newitem);
                // rebuild list
                filterstring = null;
                prevfilterstring = null;
            }
        }

        if (variables.containsKey(FOCUS_EVENT_ID)) {
            fireEvent(new FocusEvent(this));
        }
        if (variables.containsKey(BLUR_EVENT_ID)) {
            fireEvent(new BlurEvent(this));
        }

    }

    @Override
    public void requestRepaint() {
        super.requestRepaint();
        optionRequest = false;
        prevfilterstring = filterstring;
        filterstring = null;
    }

    private void optionRepaint() {
        super.requestRepaint();
    }

    public void setFilteringMode(int filteringMode) {
        this.filteringMode = filteringMode;
    }

    public int getFilteringMode() {
        return filteringMode;
    }

    /**
     * Note, one should use more generic setWidth(String) method instead of
     * this. This now days actually converts columns to width with em css unit.
     * 
     * Sets the number of columns in the editor. If the number of columns is set
     * 0, the actual number of displayed columns is determined implicitly by the
     * adapter.
     * 
     * @deprecated
     * 
     * @param columns
     *            the number of columns to set.
     */
    @Deprecated
    public void setColumns(int columns) {
        if (columns < 0) {
            columns = 0;
        }
        if (this.columns != columns) {
            this.columns = columns;
            setWidth(columns, Select.UNITS_EM);
            requestRepaint();
        }
    }

    /**
     * @deprecated see setter function
     * @return
     */
    @Deprecated
    public int getColumns() {
        return columns;
    }

    public void addListener(BlurListener listener) {
        addListener(BLUR_EVENT_ID, BlurEvent.class, listener,
                BlurListener.blurMethod);
    }

    public void removeListener(BlurListener listener) {
        removeListener(BLUR_EVENT_ID, BlurEvent.class, listener);
    }

    public void addListener(FocusListener listener) {
        addListener(FOCUS_EVENT_ID, FocusEvent.class, listener,
                FocusListener.focusMethod);
    }

    public void removeListener(FocusListener listener) {
        removeListener(FOCUS_EVENT_ID, FocusEvent.class, listener);

    }

}