/** @param verticalSplit <code>true</code> means that splitter will have vertical split */
 public void setOrientation(boolean verticalSplit) {
   myVerticalSplit = verticalSplit;
   myFirstDivider.setOrientation(verticalSplit);
   myLastDivider.setOrientation(verticalSplit);
   doLayout();
   repaint();
 }
  @Override
  protected void collectInformationWithProgress(final ProgressIndicator progress) {
    final Set<HighlightInfo> gotHighlights = new THashSet<HighlightInfo>(100);
    final Set<HighlightInfo> outsideResult = new THashSet<HighlightInfo>(100);

    DaemonCodeAnalyzer daemonCodeAnalyzer = DaemonCodeAnalyzer.getInstance(myProject);
    HighlightVisitor[] highlightVisitors = getHighlightVisitors();
    final HighlightVisitor[] filteredVisitors = filterVisitors(highlightVisitors, myFile);
    final List<PsiElement> inside = new ArrayList<PsiElement>();
    final List<PsiElement> outside = new ArrayList<PsiElement>();
    try {
      Divider.divideInsideAndOutside(
          myFile,
          myStartOffset,
          myEndOffset,
          myPriorityRange,
          inside,
          outside,
          HighlightLevelUtil.AnalysisLevel.HIGHLIGHT,
          false);

      setProgressLimit((long) (inside.size() + outside.size()));

      final boolean forceHighlightParents = forceHighlightParents();

      if (!isDumbMode()) {
        highlightTodos(
            myFile,
            myDocument.getCharsSequence(),
            myStartOffset,
            myEndOffset,
            progress,
            myPriorityRange,
            gotHighlights,
            outsideResult);
      }

      collectHighlights(
          inside,
          new Runnable() {
            @Override
            public void run() {
              // all infos for the "injected fragment for the host which is inside" are indeed
              // inside
              // but some of the infos for the "injected fragment for the host which is outside" can
              // be still inside
              Set<HighlightInfo> injectedResult = new THashSet<HighlightInfo>();
              final Set<PsiFile> injected = new THashSet<PsiFile>();
              getInjectedPsiFiles(inside, outside, progress, injected);
              if (!addInjectedPsiHighlights(
                  injected, progress, Collections.synchronizedSet(injectedResult)))
                throw new ProcessCanceledException();
              final List<HighlightInfo> injectionsOutside =
                  new ArrayList<HighlightInfo>(gotHighlights.size());

              Set<HighlightInfo> result;
              synchronized (injectedResult) {
                // sync here because all writes happened in another thread
                result = injectedResult;
              }
              for (HighlightInfo info : result) {
                if (myPriorityRange.containsRange(info.getStartOffset(), info.getEndOffset())) {
                  gotHighlights.add(info);
                } else {
                  // nonconditionally apply injected results regardless whether they are in
                  // myStartOffset,myEndOffset
                  injectionsOutside.add(info);
                }
              }

              if (outsideResult.isEmpty() && injectionsOutside.isEmpty()) {
                return; // apply only result (by default apply command) and only within inside
              }

              final ProperTextRange priorityIntersection =
                  myPriorityRange.intersection(new TextRange(myStartOffset, myEndOffset));
              if ((!inside.isEmpty() || !gotHighlights.isEmpty())
                  && priorityIntersection
                      != null) { // do not apply when there were no elements to highlight
                // clear infos found in visible area to avoid applying them twice
                final List<HighlightInfo> toApplyInside =
                    new ArrayList<HighlightInfo>(gotHighlights);
                myHighlights.addAll(toApplyInside);
                gotHighlights.clear();
                gotHighlights.addAll(outsideResult);
                final long modificationStamp = myDocument.getModificationStamp();
                UIUtil.invokeLaterIfNeeded(
                    new Runnable() {
                      @Override
                      public void run() {
                        if (myProject.isDisposed()
                            || modificationStamp != myDocument.getModificationStamp()) return;
                        MarkupModel markupModel =
                            DocumentMarkupModel.forDocument(myDocument, myProject, true);

                        UpdateHighlightersUtil.setHighlightersInRange(
                            myProject,
                            myDocument,
                            priorityIntersection,
                            getColorsScheme(),
                            toApplyInside,
                            (MarkupModelEx) markupModel,
                            Pass.UPDATE_ALL);
                        if (myEditor != null) {
                          new ShowAutoImportPass(myProject, myFile, myEditor)
                              .applyInformationToEditor();
                        }
                      }
                    });
              }

              myApplyCommand =
                  new Runnable() {
                    @Override
                    public void run() {
                      ProperTextRange range = new ProperTextRange(myStartOffset, myEndOffset);

                      List<HighlightInfo> toApply = new ArrayList<HighlightInfo>();
                      for (HighlightInfo info : gotHighlights) {
                        if (!range.containsRange(info.getStartOffset(), info.getEndOffset()))
                          continue;
                        if (!myPriorityRange.containsRange(
                            info.getStartOffset(), info.getEndOffset())) {
                          toApply.add(info);
                        }
                      }
                      toApply.addAll(injectionsOutside);

                      UpdateHighlightersUtil.setHighlightersOutsideRange(
                          myProject,
                          myDocument,
                          toApply,
                          getColorsScheme(),
                          myStartOffset,
                          myEndOffset,
                          myPriorityRange,
                          Pass.UPDATE_ALL);
                    }
                  };
            }
          },
          outside,
          progress,
          filteredVisitors,
          gotHighlights,
          forceHighlightParents);

      if (myUpdateAll) {
        ((DaemonCodeAnalyzerImpl) daemonCodeAnalyzer)
            .getFileStatusMap()
            .setErrorFoundFlag(myDocument, myErrorFound);
      }
    } finally {
      incVisitorUsageCount(-1);
    }
    myHighlights.addAll(gotHighlights);
  }
  public void doLayout() {
    final int width = getWidth();
    final int height = getHeight();

    Rectangle firstRect = new Rectangle();
    Rectangle firstDividerRect = new Rectangle();
    Rectangle lastDividerRect = new Rectangle();
    Rectangle lastRect = new Rectangle();
    Rectangle innerRect = new Rectangle();
    final int componentSize = getOrientation() ? height : width;
    int dividerWidth = getDividerWidth();
    int dividersCount = visibleDividersCount();

    int firstCompontSize;
    int lastComponentSize;
    int innerComponentSize;
    if (componentSize <= dividersCount * dividerWidth) {
      firstCompontSize = 0;
      lastComponentSize = 0;
      innerComponentSize = 0;
      dividerWidth = componentSize;
    } else {
      firstCompontSize = getFirstSize();
      lastComponentSize = getLastSize();
      int sizeLack =
          firstCompontSize + lastComponentSize - (componentSize - dividersCount * dividerWidth);
      if (sizeLack > 0) {
        // Lacking size. Reduce first component's size, inner -> empty
        firstCompontSize -= sizeLack;
        innerComponentSize = 0;
      } else {
        innerComponentSize =
            componentSize - dividersCount * dividerWidth - getFirstSize() - getLastSize();
      }

      if (!innerVisible()) {
        lastComponentSize += innerComponentSize;
        innerComponentSize = 0;
        if (!lastVisible()) {
          firstCompontSize = componentSize;
        }
      }
    }

    if (getOrientation()) {
      int space = firstCompontSize;
      firstRect.setBounds(0, 0, width, firstCompontSize);
      if (firstDividerVisible()) {
        firstDividerRect.setBounds(0, space, width, dividerWidth);
        space += dividerWidth;
      }

      innerRect.setBounds(0, space, width, innerComponentSize);
      space += innerComponentSize;

      if (lastDividerVisible()) {
        lastDividerRect.setBounds(0, space, width, dividerWidth);
        space += dividerWidth;
      }

      lastRect.setBounds(0, space, width, lastComponentSize);
    } else {
      int space = firstCompontSize;
      firstRect.setBounds(0, 0, firstCompontSize, height);

      if (firstDividerVisible()) {
        firstDividerRect.setBounds(space, 0, dividerWidth, height);
        space += dividerWidth;
      }

      innerRect.setBounds(space, 0, innerComponentSize, height);
      space += innerComponentSize;

      if (lastDividerVisible()) {
        lastDividerRect.setBounds(space, 0, dividerWidth, height);
        space += dividerWidth;
      }

      lastRect.setBounds(space, 0, lastComponentSize, height);
    }

    myFirstDivider.setVisible(firstDividerVisible());
    myFirstDivider.setBounds(firstDividerRect);
    myFirstDivider.doLayout();

    myLastDivider.setVisible(lastDividerVisible());
    myLastDivider.setBounds(lastDividerRect);
    myLastDivider.doLayout();

    validateIfNeeded(myFirstComponent, firstRect);
    validateIfNeeded(myInnerComponent, innerRect);
    validateIfNeeded(myLastComponent, lastRect);
  }